C++学习笔记(Thinking in C++)五

    技术2022-05-19  25

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

     

     


    最新回复(0)