首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

问个虚函数相关有关问题

2012-02-21 
问个虚函数相关问题classCParent{public:CParent(){Print()}virtual~CParent(){}virtualvoidPrint(){std:

问个虚函数相关问题
class   CParent
{
    public:
        CParent()
        {
            Print();
        }
        virtual   ~CParent(){}
        virtual   void   Print()
        {
            std::cout < < "1, ";
        }
};

class   CSon:public   CParent
{
    public:
        CSon()
        {
            Print();
        }
        virtual   ~CSon(){}
        void   Print()
        {
            std::cout < < "2, ";
        }
};

main()
{
    CParent   *pParent   =   new   CSon();
    delete   pParent;
}

这个程序调用基类和派生类的构造函数后,分别调用Print这个虚函数的输出是什么?为什么?

[解决办法]
不要在构造函数中调用虚函数。
因为父类构造函数在执行时,子类对象还没构造好。
[解决办法]
输出为1,2
调用基类构造函数时子类还没有构造 因此 很显然的 基类没有子类的vtbl的信息
所以基类静态调用自身的print()
[解决办法]
《Effective C++》上有讲,总之,就是不要在构造或者析构函数里调用虚函数。
其行为通常并不能表现得像一般的虚函数。

具体可以自己看看那个书。
[解决办法]
输出为1,2。
构造CSon时,首先去初始化this指针,然后会去调用基类CParent的构造函数,
CParent同样也是去初始化this指针,如果还有基类的话,那么会继续调用基类的构造函数。如果没有就会构造他自己的虚表和虚指针。然后进入构造函数,调用完后,返回CSon构造函数,初始化虚表和虚指针(需要根据基类的虚表的信息,如果派生类没有重写基类的虚方法,那么就会将基类该虚方法的入口地址拷入自己的虚表中,如果派生类改写了虚方法,就会将改写的虚方法的入口地址写入自己的虚表中),最后在进入自己的构造函数中。
所有我们可以看到,当基类构造函数调用虚方法的时候,他的虚表地址是由基类构造的,所以将会调用基类的虚方法,而在派生类构造函数的调用时,虚表是由派生类构造的,这时候入口地址已经被重写了。
[解决办法]
就是不要在构造或者析构函数里调用虚函数。
其行为通常并不能表现得像一般的虚函数.

这个是正解,也要千万注意,不要在构造或者析构函数里调用虚函数。
这个不是面向对象本身的问题,是C++的问题。

具体原因,你还是把C++对虚函数的内容实现看一看会对你有帮助的。
我的blog里有一个说C++的虚函数的的小文章。希望对你能有帮助。

[解决办法]
不要在构造或者析构函数里调用虚函数
构造函数和析构函数不是一般的函数
[解决办法]
构造函数当中没有多态行为的
[解决办法]
怎么可能编译器就构造好的,那时候对象还没建立,没有空间,就没有地址,怎么可能就确定呢
[解决办法]
通常情况下是一个类一个虚表,但在多继承情况下可能具有多个虚表。安插虚表和虚指针都是由构造函数负责的,不太清楚的话,可以去看看《C++对象模型》
[解决办法]
“构造CSon时,首先去初始化this指针,然后会去调用基类CParent的构造函数,。。”

不好意思这里有点笔误,构造某个类的时候,首先回去调用基类的构着函数,如果基类还有基类的话,会继续去构造基类,如果没有的话,才会调用自身的构造函数,编译器会在构造函数中安插一些额外的代码去完成一些工作,例如初始化虚表和虚指针。this指针不属于改对象的一部分,只是指向该对象的一个指针。
[解决办法]
通常情况下是一个类一个虚表,但在多继承情况下可能具有多个虚表。安插虚表和虚指针都是由构造函数负责的,不太清楚的话,可以去看看《C++对象模型》

又是笔误,不好意思,不是类,是一个对象有一个虚表
[解决办法]
对象构造的时候与进化很相似,先让自己成为一个基类实例,再让自己成为一个派生类实例。所以虚表也是在这个过程中逐步变化的。

一个对象的虚表不是一下子就构造出来的!参考《深度探索C++对象模型》,我记得有专门的讨论。


[解决办法]
CParent()
{
Print(); //调用的是父类的
}

CSon()
{
Print(); //调用的是子类的
}

//因为构造函数会先设置vptr,即CParent()会将对象的vptr指向CParent的虚表,CSon()会将对象的vptr指向CSon的虚表。

这样CSon对象构造完成后,vptr指向的是CSon的虚函数表。


热点排行