C++之类对象创建的先后顺序

本篇文章会深入的讲解在类对象创建的时候,构造函数、析构函数的调用顺序以及普通成员变量和静态成员变量的创建顺序。

* 析构函数的调用顺序与构造函数正好相反。


1、先看如下代码,注意:构造函数和析构函数一定是要public,因为系统是要自动去调用的,不然编译会出错。

     * 类B继承于类A

 

class A
{
public:
	A()
	{
		cout << "A()" << endl;
	}
	~A()
	{
		cout << "~A()" << endl;
	}
};

class B : public A
{
public:
	B()
	{
		cout << "B()" << endl;
	}
	~B()
	{
		cout << "~B()" << endl;
	}
};

int _tmain(int argc, _TCHAR* argv[])
{
	B b;
	return 0;
}

解析:对于单继承的时候,对于构造方法的调用是先调用父类再调用子类,而对于析构方法是先调用子类再调用父类,结果如下:

A()
B()
~B()
~A()



2、多继承的时候

    * C继承B、A

class A
{
public:
	A()
	{
		cout << "A()" << endl;
	}
	~A()
	{
		cout << "~A()" << endl;
	}
};

class B
{
public:
	B()
	{
		cout << "B()" << endl;
	}
	~B()
	{
		cout << "~B()" << endl;
	}
};

class C : public B, public A
{
public:
	C()
	{
		cout << "C()" << endl;
	}
	~C()
	{
		cout << "~C()" << endl;
	}
};

int _tmain(int argc, _TCHAR* argv[])
{
	C c;
	return 0;
}


解析:对于多继承的时候构造函数和析构函数的调用顺序还是一样,构造:先父后子。析构:先子后父。但是各个父类调用的顺序要按继承的顺序调用,本例为
class C : public B, public A
所以构造函数:先B再A,析构:先A再B

结果如下:

B()
A()
C()
~C()
~A()
~B()


3、当成员变量是类的时候

 

using namespace std;

class A
{
public:
	A()
	{
		cout << "A()" << endl;
	}
	A(int x)
	{
		cout << "A(" << x << ")" << endl;
	}
	~A()
	{
		cout << "~A()" << endl;
	}
};

class B : public A
{
public:
	B():a1(1),a2(2)
	{
		cout << "B()" << endl;
	}
	~B()
	{
		cout << "~B()" << endl;
	}

private:
	A a2;
	A a1;
};

int _tmain(int argc, _TCHAR* argv[])
{
	B b;
	return 0;
}

分析:类B中含有两个类A的对象a2、a1,当b对象被创建的时候,先去创建类A中的资源,再来创建类B中的资源。所以此列先调用了类A的构造函数,因为类A中没有其他成员变量了,所以接下来创建类B的资源,所以先将类B中的所有变量创建好,即如果是类对象就会去调用相应的构造函数,最后再去调用类B的构造函数。

结果如下:

A()
A(2)
A(1)
B()
~B()
~A()
~A()
~A()



接下来是一个列子,如果看懂了的话,就表示前面的调用关系你都清楚了:

class A
{
public:
	A()
	{
		cout << "A()" << endl;
	}
	A(int x)
	{
		cout << "A(" << x << ")" << endl;
	}
	~A()
	{
		cout << "~A()" << endl;
	}
};

class B : public A
{
public:
	B():a2(2),a1(1)
	{
		cout << "B()" << endl;
	}
	B(int x)
	{
		cout << "B(" << x << ")" << endl;
	}
	~B()
	{
		cout << "~B()" << endl;
	}

private:
	A a2;
	A a1;
};

class C
{
public:
	C()
	{
		cout << "C()" << endl;
	}
	C(int x)
	{
		cout << "C(" << x << ")" << endl;
	}
	~C()
	{
		cout << "~C()" << endl;
	}
};

class D : public C, public B
{
public:
	D():b(3)
	{
		cout << "D()" << endl;
	}
	D(int x)
	{
		cout << "D(" << x << ")" << endl;
	}
	~D()
	{
		cout << "~D()" << endl;
	}

private:
	B b;
};

int _tmain(int argc, _TCHAR* argv[])
{
	D d;
	return 0;
}

分析:你可以画一颗继承树,然后把相应节点上的类所需要的成员变量写到傍边,然后利用中序遍历去遍历这颗树,每个节点按以上的规则(先成员变量(先定义先创建),再构造函数)---个人见解,仅供参考。


结果如下:

C()
A()
A(2)
A(1)
B()
A()
A()
A()
B(3)
D()
~D()
~B()
~A()
~A()
~A()
~B()
~A()
~A()
~A()
~C()


下面是关于静态成员变量的初始化及其顺序。


class A
{
public:
	A()
	{
		cout << "A()" << endl;
	}
	~A()
	{
		cout << "~A()" << endl;
	}
public:
	static A a;

};

int _tmain(int argc, _TCHAR* argv[])
{
	return 0;
}


结果:无


class A
{
public:
	A()
	{
		cout << "A()" << endl;
	}
	A(int x)
	{
		cout << "A(" << x << ")" << endl;
	}
	~A()
	{
		cout << "~A()" << endl;
	}
};

class B : public A
{
public:
	B()
	{
		cout << "B()" << endl;
	}
	B(int x)
	{
		cout << "B(" << x << ")" << endl;
	}
	~B()
	{
		cout << "~B()" << endl;
	}

public:
	static A a; 
};

static B::A a(1); 

int _tmain(int argc, _TCHAR* argv[])
{
	B b;
	return 0;
}

结果:

A(1)
A()
B()
~B()
~A()
~A()



 

分析:通过前面两段代码和结果,可以看出当静态成员变量调用语句static B::A a; 初始化时它就不会被初始化,而一旦有这条语句就会在编译的时候就初始化了。



现在可以讲以上的知识连在一起了。

class A
{
public:
	A()
	{
		cout << "A()" << endl;
	}
	A(int x)
	{
		cout << "A(" << x << ")" << endl;
	}
	~A()
	{
		cout << "~A()" << endl;
	}
};

class B : public A
{
public:
	B():a2(2),a1(1)
	{
		cout << "B()" << endl;
	}
	B(int x)
	{
		cout << "B(" << x << ")" << endl;
	}
	~B()
	{
		cout << "~B()" << endl;
	}

private:
	A a2;
	A a1;

public:
	static A a3;
};

class C
{
public:
	C()
	{
		cout << "C()" << endl;
	}
	C(int x)
	{
		cout << "C(" << x << ")" << endl;
	}
	~C()
	{
		cout << "~C()" << endl;
	}
};

class D : public C, public B
{
public:
	D():b(3)
	{
		cout << "D()" << endl;
	}
	D(int x)
	{
		cout << "D(" << x << ")" << endl;
	}
	~D()
	{
		cout << "~D()" << endl;
	}

private:
	B b;

public:
	static A a;
	static A aa;
};

A D::aa(1);
A D::a(2);
A B::a3(3);


int _tmain(int argc, _TCHAR* argv[])
{
	D d;
	return 0;
}



结果如下:

A(3)
C()
A()
A(2)
A(1)
B()
A()
A()
A()
B(3)
D()
~D()
~B()
~A()
~A()
~A()
~B()
~A()
~A()
~A()
~C()
~A()
~A()
~A()



 

* 记住静态变量的初始化也是按初始化语句的先后顺序进行的。


虽然上面的知识深入没有什么意识,不过了解一点总好,平时不注意,笔试的时候就坑了。



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值