您的位置:首页 > 编程语言 > C语言/C++

C++ - 对象模型之 构造和析构函数都干了什么

2014-11-27 17:15 357 查看
转自: http://blog.csdn.net/gykimo/article/details/8629896
C++ - 对象模型之 构造和析构函数都干了什么

我们知道,编译器背着我们做了很多其他的事情,这些事情最为复杂的就是构造函数、拷贝构造函数和析构函数。本部分主要分析,编译器给构造函数、析构函数等都增加了什么功能。

构造和析构函数

无继承

如C++代码:

class Toy
{
public:
Toy(){};
virtual ~Toy(){}

private:
virtual void play(){printf("play the toy\n");}
};

class Child
{
public:
Child():Age(10),name("小明"){}
virtual void who(){printf("I am child\n");}
virtual ~Child(){}

private:
int Age;
Toy toy;
char* name;
};

int main(){
Child child;
}

可能会被转化为如下伪码:

Child::Child(){
//设置vptr
this->__vptr_Child = __vtbl_Child;
//初始化列表
Age = 10;
name = "小明";
toy::Toy();
}

Child::~Child(){
toy::~Toy();
}

int main(){
Child child;
child::Child();

child::~Child();
}

可见至少要做如下几件事情:

构造函数
1. 如果有虚函数,那么先设定vptr指向应该指向的vtbl;
2. 出现在初始化列表中的初始化操作会在构造函数中执行;
3. 如果member object有Default构造函数,即使没有出现在初始化列表中,也要在构造函数中调用该member的构造函数;

析构函数:
1. 如果member object有析构函数,那么要在析构函数中调用该member的析构函数进行析构;

继承

#include <stdio.h>
#include <typeinfo.h>

class GrandFather
{
public:
GrandFather(){who();}
virtual void who(){printf("I am GrandFather\n");}
~GrandFather(){who();}
void func(){}
};


class Father : public GrandFather
{
public:
Father(){who();}
~Father(){who();}
};

class Child : public Father
{
public:
Child(){who();}
virtual void who(){printf("I am child\n");}
virtual ~Child(){who();}

private:
int Age;
};

int main(){
Child child;
}


伪码:

class GrandFather
{
public:
GrandFather(){
//设置vptr
this->__vptr = __vtbl_GrandFather;
who();
}
virtual void who(){printf("I am GrandFather\n");}
~GrandFather(){
//设置vptr
this->__vptr = __vtbl_GrandFather;
who();
}
};


class Father : public GrandFather
{
public:
Father(){
GrandFather::GrandFather();
//设置vptr
this->__vptr = __vtbl_Father;
who();
}
~Father(){
//设置vptr
this->__vptr = __vtbl_Father;
who();
GrandFather::~GrandFather();
}
};

class Child : public Father
{
public:
Child(){
Father::Father();
//设置vptr
this->__vptr = __vtbl_Child;
who();
}
virtual void who(){printf("I am child\n");}
virtual ~Child(){
//设置vptr
this->__vptr = __vtbl_Child;
who();
Father::~Father();
}

private:
int Age;
};

int main(){
Child child;
child::Child();
}

结果:
I am GrandFather

I am GrandFather

I am child

I am child

I am GrandFather

I am GrandFather

分析:
1. 构造函数先调用base的构造函数,后设置其他变量,包括vptr;
2. 构造函数调用虚函数,会调用它的vptr设置的虚函数,也就是说vptr的该虚函数。该案例,在对象创建过程中,who()会依次调用GrandFather的who(),然后是Father的,由于Father没有重写who,所以调用的还是GrandFather的,最后到了child,调用的是child的who,也就是在创建过程中,对象的类型依次是GrandFather、Father、Child;
3. 析构函数,会首先设置vptr,最后,才调用base的析构函数。所以,在析构过程中,对象的类型,依次是Child、Father、GrandFather;

赋值操作

还记得复制构造函数的bitwise copy吗?赋值操作也有bitwise copy,只要不满足下面的四种情况,对象赋值时,就采用bitwise copy:

1. 内有member object,并且该member class定义了copy assignment operator;

试想,如果我们还是使用bitwise copy,那么该member的copy assignment operator将不会被调用。

2. base class有copy assignment operator

3. 声明了任何的virtual functions

如果一个无继承的类,有virtual functions,是否也不满足bitwise copy呢?我认为,这个时候应该可以进行bitwise copy

4. 继承一个virtual base class
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: