Skip to content

Instantly share code, notes, and snippets.

@baiyanhuang
Created July 10, 2012 12:42
Show Gist options
  • Save baiyanhuang/3083031 to your computer and use it in GitHub Desktop.
Save baiyanhuang/3083031 to your computer and use it in GitHub Desktop.
test the object construction sequence
#include <iostream>
using namespace std;
class Base
{
public:
Base() {cout << "Base constructor called" << endl;}
};
class Base1: virtual public Base
{
public:
Base1() {cout << "Base1 constructor called" << endl;}
};
class Base2: virtual public Base
{
public:
Base2() {cout << "Base2 constructor called" << endl;}
};
class Derived1: public Base1
{
public:
Derived1() {cout << "Derived1 constructor called" << endl;}
};
class Derived2: public Base2
{
public:
Derived2() {cout << "Derived2 constructor called" << endl;}
};
class BaseVirtualFunc
{
public:
BaseVirtualFunc()
{
cout << "BaseVirtualFunc constructor called" << endl;
virtual_foo();
}
virtual void virtual_foo() {cout << "BaseVirtualFunc::virtual_foo called" << endl;}
};
class TheMember
{
public:
TheMember()
{
cout << "TheMember constructor called: default" << endl;
}
TheMember(int i)
{
cout << "TheMember constructor called:" << i << endl;
}
TheMember(BaseVirtualFunc* virt)
{
cout << "TheMember constructor called: BaseVirtualFunc" << endl;
virt->virtual_foo();
}
};
class TheObject: public BaseVirtualFunc, public Derived1, public Derived2
{
private:
TheMember member0;
TheMember member1;
TheMember member2;
TheMember member3;
public:
TheObject():
member3(3), member2(2), member0(this)
{
cout << "TheObject constructor called" << endl;
}
virtual void virtual_foo() {cout << "TheObject::virtual_foo called" << endl;}
};
int main()
{
TheObject obj;
}
一个复杂的C++对象构造,大概可以分为4步 - 这里复杂是指有多重继承,虚继承,基类有虚函数, 以及有类成员等等。
1. 调用基类构造函数 - 由深到浅,由左至右, 如有虚拟继承,虚基类构造函数最先调用
2. 子类vptr初始化
3. 成员初始化 - 不管初始化列表中的顺序,也不管是否出现在初始化列表中,一律按照声明次序
4. 构造函数体
按照此顺序,把下面输出归类:
1. 调用基类构造函数 - 由深到浅,由左至右, 如有虚拟继承,虚基类构造函数最先调用
Base(virtual) constructor called
PolyBase constructor called
PolyBase::virtual_foo called
Base1 constructor called
Derived1 constructor called
Base2 constructor called
Derived2 constructor called
2. 子类vptr初始化 - 这里通过在基类构造函数PolyBase::PolyBase()和子类第一个初始化成员TheMember(PolyBase* virt)的构造函数中调用虚函数virtual_foo,可以看到调用了不同的虚函数实现,从而可以证明vptr的初始化是在基类构造函数之后,子类成员初始化之前。
TheMember constructor called: PolyBase
TheObject::virtual_foo called
3. 成员初始化 - 不管初始化列表中的顺序,也不管是否出现在初始化列表中,一律按照声明次序
TheMember constructor called: default
TheMember constructor called:2
TheMember constructor called:3
4. 构造函数体
TheObject constructor called
Base(virtual) constructor called
PolyBase constructor called
PolyBase::virtual_foo called
Base1 constructor called
Derived1 constructor called
Base2 constructor called
Derived2 constructor called
TheMember constructor called: PolyBase
TheObject::virtual_foo called
TheMember constructor called: default
TheMember constructor called:2
TheMember constructor called:3
TheObject constructor called
@baiyanhuang
Copy link
Author

这里可以看出,在基类构造函数中调用虚函数,无法调用到子类的实现,原因就在于子类vptr的初始化在基类构造函数之后, 一些纯虚函数的调用即出于此。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment