虚基类多态的调试

来源:互联网 发布:java 邮件发送附件 编辑:程序博客网 时间:2024/05/16 10:53

//**************by er lei2009-10-16********************//

 

声明两个类:

class Base
{
    public:
    Base()
    {
        cout<<"Base Init/n";
    }
    virtual ~Base()
    {
        cout<<"Base ~~/n";
    }
    void DoSome()
    {
        cout<<"Base DoSom/n";
    }
};
class Derived : public Base
{
    public:
    Derived()
    {
        cout<<"Derived Init /n";
    }
    virtual ~Derived()
    {
        cout<<"Derived ~~/n";
    }
    void DoSome()
    {
         cout<<"Derived DoSome /n";
    }
};

int main(int argc, char* argv[])
{

   // Derived * d = new Base();这样写是错误的 因为基类不包含全部子类成员所以不能用基类初始化
    Base * d = new Derived();  //这样写是对的 在new Derived的过程中调用了d的构造函数

    while (1)
    {}
}

程序输出如下:

Base Init
Derived Init

main函数修改一下

int main(int argc, char* argv[])
{
    Base * d = new Derived(); //用子类初始化父类
    d->DoSome(); //调用的是父类的函数
    delete d; 
    while (1)
    {}
}

程序输出如下:

Base Init            初始化子类
Derived Init        初始化父类
Base DoSom      调用父类函数
Derived ~~        调用子类析构函数
Base ~~            调用父类析构函数

现在我们把基类和子类该一下

把子类的析构函数的virtual去掉

class Base
{
    public:
    Base()
    {
        cout<<"Base Init/n";
    }
    ~Base()
    {
        cout<<"Base ~~/n";
    }
    void DoSome()
    {
        cout<<"Base DoSom/n";
    }
};
class Derived : public Base
{
    public:
    Derived()
    {
        cout<<"Derived Init /n";
    }
    ~Derived()
    {
        cout<<"Derived ~~/n";
    }
    void DoSome()
    {
         cout<<"Derived DoSome /n";
    }
};

int main(int argc, char* argv[])
{
    Base * d = new Derived();
    d->DoSome();    //调用的是基类的函数
    delete d;          //只调用基类的析构函数
    while (1)
    {}
}

输出如下:

Base Init  
Derived Init
Base DoSom
Base ~~
再改一下程序:析构和DoSome函数都加上virtual

 

class Base
{
    public:
    Base()
    {
        cout<<"Base Init/n";
    }
    virtual ~Base()
    {
        cout<<"Base ~~/n";
    }
    virtual void DoSome()
    {
        cout<<"Base DoSom/n";
    }
};
class Derived : public Base
{
    public:
    Derived()
    {
        cout<<"Derived Init /n";
    }
    ~Derived()
    {
        cout<<"Derived ~~/n";
    }
    void DoSome()
    {
         cout<<"Derived DoSome /n";
    }
};
int main(int argc, char* argv[])
{
    Base * d = new Derived();
    d->DoSome();
    delete d;
    while (1)
    {}
}

程序输出如下

Base Init
Derived Init
Derived DoSome 子类的函数
Derived ~~
Base ~~

咱么现在来总结一下:

在基类用子类构造的前提下

若基类的DoSome是虚函数

则调用子类的DoSome函数

若基类的DoSome不是虚函数

则调用基类的DoSome函数

简单来说就是这么个规律,但是为什么呢,咱么来点有深度的

编译器在编译一个有虚函数的类时会为此类生成一个虚拟函数表vtable

表的值就是指向虚函数地址的指针

在调用类的构造函数时,指向基础类的指针此时已经变成指向具体的类的this指针,这样依靠此this指针即可得到正确的vtable,从而实现了多态性。在此时才能真正与函数体进行连接,这就是动态联编。

 

原创粉丝点击