1、关于虚函数一些注意点
class Base{ public: virtual void display(){ cout<<"Base display"<<endl; } }; class CTest: public Base{ public: void display(){ cout<<"CTest display"<<endl; } }; void fun(Base &b){ b.display(); } void fun2(Base b){ b.display(); } void fun3(Base *b){ b->display(); } int main(void){ CTest ct; fun(ct); fun2(ct); fun3(&ct); return 0; }
重点:要实现虚函数的效果,必须在参数调用的时候实用指针或者引用,如果使用值传递的话,则会调用基类的函数。这是因为每个有许函数的类编译器都会创建一个vtable,并且他们的vptr都在相同的位置。如果使用值传递,则派生类的vtable不会被拷贝到基类对象中。
2、当继承几个抽象基类时,必须实现所有的纯虚函数,否则继承出的类也将是一个抽象类。
如果类中声明一个纯虚函数,则这个类的VTABLE就是不完全的。
在基类中,对纯虚函数提供定义是可能的。但是不能定义为inline函数。例如下面这种方式:
class base{
public:
virtual void show()=0 {cout <<"base:"<<endl;}//错误:这种inline方式定义纯虚函数是错误的。
virtual void display() = 0;
};
void base::display(){cout<<"base"<<endl;}//正确的定义。
纯虚函数的原理:
至于纯虚函数的实现 virtual void x() = 0; 这句,等于告诉编译器在VTABLE中为函数保留一个间隔,但在这个特定间隔 中不放地址。只要有一个函数在类中被声明为纯虚函数,则VTABLE就是不完全的 这样当某人试图创建这个类时,编译器会由于不能安全的创建一个纯抽象类的对象 而发出一个出错信息,这样编译器就可以保证抽象类的纯洁性,不会被误用
3、类型转化的问题;
1 #include <iostream> 2 using namespace std; 3 4 class NVBase{ 5 public: 6 void display(){} 7 }; 8 class VBase{ 9 public: 10 virtual void display(){} 11 }; 12 class CNVBA: public NVBase{}; 13 class CNVBB: public NVBase{}; 14 15 class CVBA:public VBase{}; 16 class CVBB:public VBase{}; 17 18 class COther{}; 19 20 int main(void){ 21 NVBase* b = new CNVBA; 22 CNVBA *cta = static_cast<CNVBA *>(b); 23 CNVBB *ctb = static_cast<CNVBB *>(b); 24 //COther *cos = static_cast<COther *>(b);//error: invalid static_cast from type ‘NVBase*’ to type ‘COther*’ 25 cout<<"NVBA:"<<(long)cta<<" NVBB:"<<(long)ctb<<" other:"<<(long)cos<<endl; 26 //输出是:NVBA:143290376 NVBB:143290376 other:
27 //CNVBA *ctad = dynamic_cast<CNVBA *>(b);//error:(source type is not polymorphic 28 //CNVBB *ctbd = dynamic_cast<CNVBB *>(b);//error:(source type is not polymorphic 29 //COther *cod = dynamic_cast<COther *>(b);//error:(source type is not polymorphic 30 31 VBase* vb = new CVBA; 32 CVBA *vba = static_cast<CVBA *>(vb); 33 CVBB *vbb = static_cast<CVBB *>(vb); 34 COther *vcos = static_cast<COther *>(vb);//error: invalid static_cast from type ‘NVBase*’ to type ‘COther*’ 35 cout<<"VBA:"<<(long)vba<<" VBB:"<<(long)vbb<<" other:"<<(long)vcos<<endl;
//输出是:VBA:143290392 VBB:143290392 other: 36 37 CVBA *vbad = dynamic_cast<CVBA *>(vb); 38 CVBB *vbbd = dynamic_cast<CVBB *>(vb); 39 COther *vcod = dynamic_cast<COther *>(vb); 40 cout<<"VBA:"<<(long)vbad<<" VBB:"<<(long)vbbd<<" other:"<<(long)vcod<<endl;
//输出是:VBA:143290392 VBB:0 other:0
41 return 0; 42 } 综上所述,static_cast<>可以实现非虚和虚函数的转化,但是不支持非派生类的向下转化;dynamic_cast<>只能实现有虚函数的向下转化;强制转化COther *o=(COther*) vb;或者b都可以实现强制转化。