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

C++对象模型目录

C++ - 对象模型之 编译器何时才会自行添加构造函数

C++ - 对象模型之 内存布局

C++ - 对象模型之 成员函数调用

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

C++ - 对象模型之 类对象在执行时是如何生成的

C++ - 对象模型之 模板、异常、RTTI的实现


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


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值