C++交流群: 302558294(欢迎你的加入)


谈谈关于构造函数中调用虚函数的情况,仅讨论单继承,不考虑虚拟继承和多重继承。



测试平台:VS2013 + Win7X64



一个例子:


#include <stdlib.h>


#include <stdio.h>



class Base


{


private:


    int __data;



public:


    Base()


    {


        this->Func();


    }



public:


    virtual void Func()


    {


        printf("Base::Func");


    }


};



class Deri : public Base


{


public:


    Deri()


    {


        this->Func();
    }


public:
    virtual void Func()
    {
        printf("Deri::Func\n");
    }

};

int main(int argc, char** argv)
{
    Deri d;

    getchar();
    return 0;
}



输出:


Base::Func


Deri::Func





1 先构造基类部分,调用基类Base的构造函数,这个时候,派生类部分还没有产生,这时候虚表应该是绑定基类的,自然调用的是Base::Func()



2 再构造派生类部分,这个时候,虚表发生变化,绑定在派生类上,调用Deri::Func()



虽然,在派生类中有重载Func这个函数,但是,在构造基类部分的时候,派生类的成员数据还没有初始化,如果是调用派生类中的Func,会造成错误,内存越界甚至崩溃。







-- Base::Func()


int* vtl = (int*)*((int*)this);



std::cout << "Base: " << this << "  VTable: " << vtl << std::endl;



-- Deri::Func()



int* vtl = (int*)*((int*)this);



std::cout << "Deri: " << this << "  VTable: " << vtl << std::endl;



输出:


Base: 0028F980  VTable: 003FDC78
Deri: 0028F980  VTable: 003FDC98



发现,虚表的地址是不断变化的。