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都可以实现强制转化。