考虑virtual函数以外的选择】的更多相关文章

在C++中,有四种选择可以替代virtual函数的功能: 1.non-virtual interface(NVI)手法,这是一种template method模式.它以public non-virtual成员函数包含较低访问性的virtual函数.对于子类而言,子类只需重定义私有的virtual函数即可. 2.将virtual函数替换为"函数指针成员变量",这是Strategy模式的一种表现形式.这种方案的优点在于,将类和行为分离(比如相同的类的不同对象可以具有不同的行为):缺点在于,…
游戏中的人物伤害值计算问题. (一)方法(1):一般来讲能够使用虚函数的方法: class GameCharacter { public: virtual int healthValue() const; //返回人物的体力值,派生类能够做出改动 ... }; 这确实是一个显而易见的设计选择.但由于这种设计过于显而易见,可能不会对其他可选方法给予足够的关注.我们来考虑一些处理这个问题的其他方法. (二)方法(2):使用NVI方法,在基类中使用一个公有的普通函数调用私有的虚函数. class Ga…
virtual函数的替代方案包括NVI手法及Strategy设计模式的多种手法.NVI手法自身是一个特殊形式的Template Method设计模式. 将机能从成员函数移到class外部函数,带来的一个缺点是,非成员函数无法访问class的non-public成员. tr1::function对象的行为就想一般函数指针.这样的对象可接纳“与给定之目标签名式(target signature)兼容”的所有可调用物(callable entities).…
详情见<Effective C++>item35 1.使用non-virtual interface(NVI)手法,这是Template Method设计模式的一种特殊形式. 它以public non-virtual成员函数包裹较低访问性(private 或 protected)的virtual函数. 2.strategy设计模式 a.将virtual 函数替换为“函数指针成员变量” b.以tr1::function成员变量替换virtual函数,因而允许使用任何可调用物搭配一个兼容于需求的签…
举书上的例子,考虑一个virtual函数的应用实例: class GameCharacter { private: int BaseHealth; public: virtual int GetHealthValue() const // 返回游戏人物的血量 { return BaseHealth; } int GetBaseHealth() const { return BaseHealth; } }; class KnightBoss : public GameCharacter { pub…
有一部分人总是主张virtual函数几乎总应该是private:例如下面这个例子,例子时候游戏,游戏里面的任务都拥有健康值这一属性: class GameCharacter{ public: int healthValue()const{ ... int retVal = doHealthValue(); ... return retVal; } private: virtual int doHealthValue() const { }//上面的这个non-virtual函数实际上是virtu…
NOTE: 1.virtual 函数的替代方案包括NVI手法及Strategy设计模式的多种形式.NVI手法自身是一个特殊形式的Template Method设计模式. 2.将机能从成员函数移到外部函数,带来的一个缺点是,非成员函数无法访问class的non-public成员. 3.tr1::function 对象的行为就像一般函数指针.这样的对象可接纳“与给定之目标签名式(target signature)兼容”的所有可调用物(callable entiies). 不懂这条,设计模式不懂!!!…
http://blog.csdn.net/freeboy1015/article/details/7635012 为什么内联函数,构造函数,静态成员函数不能为virtual函数? 1> 内联函数 内联函数是在编译时期展开,而虚函数的特性是运行时才动态联编,所以两者矛盾,不能定义内联函数为虚函数. 2> 构造函数 构造函数用来创建一个新的对象,而虚函数的运行是建立在对象的基础上,在构造函数执行时,对象尚未形成,所以不能将构造函数定义为虚函数. 3> 静态成员函数 静态成员函数属于一个类而非…
在base class构造期间,virtual函数不是virtual函数. 构造函数.析构函数中不要调用virtual函数.…
在构造和析构期间不要调用virtual函数,因为这类调用从不下降至derived class(比起当前执行构造函数和析构函数的那层).…
如下是一个股票交易的例子: class Transaction // 交易的基类 { public: Transaction(); ; // 用于记录交易日志 }; Transaction::Transaction() { logTransaction(); // 调用虚函数 } class BuyTransaction : public Transaction // 买进股票 { virtual void logTransaction() const; }; void BuyTransacti…
绝不重新定义继承来的缺省值 首先明确下,虚函数是动态绑定,缺省参数值是静态绑定 // a class for geometric shapes class Shape { public: enum ShapeColor { Red, Green, Blue }; // all shapes must offer a function to draw themselves ; ... }; class Rectangle: public Shape { public: // notice the…
如不使用自动生成函数要明确拒绝 对于一个类,如果你没有声明,c++会自动生成一个构造函数,一个析构函数,一个copy构造函数和一个copy assignment操作符. class Empty { public: Empty() { ... } // default constructor Empty(const Empty& rhs) { ... } // copy constructor ~Empty() { ... } // destructor — see below // for wh…
当你每次看到C++类中声明一个virtual函数,特别是看到了一个virtual的虚构函数.你知道它的意思吗?你肯定会毫不犹豫的回答:不就是多态么...在运行时确定具体的行为么...完全正确,但这里我要讲的不只是这些东西. 有些类需要虚函数,有些不需要虚函数.这是为什么,一般你看到的类如果有一个虚析构函数,那么这个类中应该会有至少一个是虚函数的..这是为什么呢??如果我们类中没有用其他虚函数的话,你创建了这个也是多余的,而且会增加类对象的大小..说这些纯理论的东西,也许大家不知所云..下面我就给…
(整理自Effctive C++,转载请注明.整理者:华科小涛@http://www.cnblogs.com/hust-ghtao/) 为方便采用书上的例子,先提出问题,在说解决方案. 1 问题 1: class Transaction{ 2: public: 3: Transaction(); 4: virtual void LogTransaction() const = 0 ; 5: ... 6: }; 7:  8: Transaction::Transaction() //Base cl…
#include<iostream> #include<string> using namespace std; class Base { public: Base(){} ~Base(){} public: virtual void f1(int x){ cout << "baseclass: f1() " << x << endl; } virtual void f2()final{ cout << "…
在构造和析构执行期间不要调用virtual函数,因为这类调用从不会下降至derived class(比起当前执行构造函数和析构函数) 如果在base class 构造函数或者析构函数调用virtual,derived class构造时会先构造base class,则base class中的virtual实际调用是base class的; 第一种解释:derived class类先执行构造base class部分,然而在base class构造过程中,derived class部分是为初始化的,如…
问题聚焦: 不要在构造函数和析构函数中调用virtual函数,因为这样的调用不会带来你预想的结果. 让我先来看一下在构造函数里调用一个virtual函数会发生什么结果 Demo class Transaction { public: Transaction(); ; }; Transaction::Transaction() { logTransaction(); } //void Transaction::logTransaction() const //第一次编译时,注释掉该段代码 //{…
#include <iostream> #include <cstdlib> using namespace std; class Pen { public: ) { cout<<"write with color:"<<color<<endl; } }; class Pencil : public Pen{ public: ) { cout<<"write with color:"<&l…
看过C++对象模型的话就可以知道,在构造基类时,完整的vtable没有建立起来(表项没有被相应的子类函数替换),因而无法调用到子类的函数(即构造函数中的virtual函数是本类里的方法,不是virtual的).书中也说即使调用了,因为构造函数的调用顺序,父类在构造时子类的成员还没有初始化可能,此时调用virtual函数无疑会造成混乱. 类似的关于析构过程,是一个子类先执行然后再父类执行的过程,如果在父类中调用virtual函数那么可能涉及到的子类数据已经被释放或者重置了,应该是出于这个考虑吧.…
下面是一个用来塑模股市交易的类: derived的类的构造函数被调用,但是首先得调用基类Transaction的构造函数,但是在后面还得调用virrual函数,这个时候子类的对象的构造还没有完成,那么虚函数也就没有意思,也就可以说虚函数现在还不是虚函数,在derived class对象构造期间,对象的类型还是base类的而不是derived class.不光是virtual函数会被解析为base calss,运行期间类型信息也会把对象视为base class.所以说现在根本就还没有derived…
  1.当在一个子类当中调用构造函数,其父类构造函数肯定先被调用.如果此时父类构造函数中有一个virtual函数,子类当中也有,肯定执行父类当中的virtual函数,而此时子类当中的成员变量并未被初始化,所以无法调用子类与之对应的函数.即为指向虚函数表的指针vptr没被初始化又怎么去调用派生类的virtual函数呢?析构函数也相同,派生类先于基类被析构,又如何去找派生类相应的虚函数? 2.做法:将子类的某个函数改为non-virtual,然后在子类构造函数中传递参数给父类函数.然后父类的构造函数…
NOTE:在构造和析构期间不要调用virtual函数,因为这类调用从不下降至derived class(比起当前执行构造函数和析构函数的那层)…
不该在构造函数和析构函数期间调用virtual函数,这一点是C++与jave/C#不同的地方之一. 假设有一个class继承体系,用来模拟股市交易如买进.卖出的订单等等.这样的交易一定要经过审计,所以每当创建一个交易对象,在审计日志中也需要创建一笔适当记录. 正确的做法是在基类Transaction内将logTransaction函数改为non-virtual,然后要求派生类构造函数传递必要信息给基类Transaction的构造函数,这样那个构造函数便可安全地调用non-virtual logT…
本质上是说了:   Template Pattern & Strategy Pattern 详细见<C++设计模式 23种设计模式.pdf 55页> 宁可要组合 不要继承. —————————————————————————————————————————— 要先看懂策略模式…
看下面的这段代码,问 print调用的是基类还是派生类的版本? 答案是 基类... 可能大家会很惊讶,print不是virtual function 吗?为什么不是调用派生类的版本呢? 首先,当定义一个派生类的对象的时候, 由于 base class 构造函数的执行更早于 derived class构造函数, 所以当 base class constructor 调用的时候,派生类的成员尚未初始化(说明,这个时候真正的 虚函数表尚未完全初始化). 如果这个时候调用 派生类的函数(可能使用未初始化…
常用的hash函数是选一个数m取模(余数),这个数在课本中推荐m是素数,但是经常见到选择m=2^n,因为对2^n求余数更快,并认为在key分布均匀的情况下,key%m也是在[0,m-1]区间均匀分布的.但实际上,key%m的分布同m是有>关的. 证明如下: key%m = key - xm,即key减掉m的某个倍数x,剩下比m小的部分就是key除以m的余数.显然,x等于key/m的整数部分,以floor(key/m)表示.假设key和m有公约数g,即key=ag, m=bg, 则 key - x…
c++中的虚函数主要是用来实现多态的,虽然都同时指向父类的实例.但调用的确实子类的函数,这个有点像java的接口和实现的关系了.一个接口有多种实现,一个接口对象调用的是哪个实现的方法,这个就是多态了 这里我写了两个类,FClass作为父类,CClass作为子类,父类和子类中都有一个fun()函数.先看一下代码 FClass.h #include <iostream> using namespace std; #ifndef __FClass__ #define __FClass__ class…
只有用指针和引用,才会动态绑定.才会在运行时候从虚表中找对应的成员函数. 如果只是用.访问成员函数,是静态绑定,在编译时刻就固定好的. 另外,父类的虚函数,子类不管加不加virtual关键字,都是虚函数.最好加上. 同样的,用指针和引用,访问普通函数的时候,不会发生多态.多态的两个条件,缺一不可. 1.upcast 2.* or &…
比如: class Base { Base() {}; ~Base() {}; virtual void Init(); }; class Derived:public Base { virtual void Init();//virtual是必须的吗? }; 答案:c++规定,当一个成员函数被声明为虚函数后,其派生类中的同名函数都自动成为虚函数.因此,在子类从新声明该虚函数时,可以加,也可以不加,但习惯上每一层声明函数时都加virtual,使程序更加清晰.…