假設(shè)我們有一個類A,另外一個類B中有個成員數(shù)據(jù)是A的對象,我們?nèi)绾蝸矶x這個成員數(shù)據(jù)呢?
最直接的,我們可以就把它定義為A的對象:A a_obj;
其次,我們可以把它定義為A對象的引用:A& a_obj; 或者const引用:const A& a_obj;
再者,我們還可以把它定義為A對象的指針:A* pA_obj; 或者const對象的指針:const A* pA_obj;
當(dāng)我們直接使用A對象的時候,a_obj會在B對象建立的時候建立,在B銷毀的時候銷毀。因為這是一個新建立的對象,所以在成員初始化的時候是真正構(gòu)造了對象,即我們前面說到的使用了復(fù)制構(gòu)造函數(shù)。
如果使用的是A對象的引用或者指針,a_obj(或pA_obj)都沒有構(gòu)造新的對象。我們假設(shè)B的一個構(gòu)造函數(shù)是這樣的:B(const A& a_obj): a_obj(a_obj) {},那么毫無疑問,這個構(gòu)造函數(shù)是能正常工作的,也就是說,我們用現(xiàn)成的對象,或者說是在B對象生命周期內(nèi)都會一直存在的A對象去構(gòu)造B對象是沒有問題的。但是,如果一個構(gòu)造函數(shù)是這樣的:B(int a): a_obj(A(a)) {},這個函數(shù),一般在編譯的時候是不會報錯或者發(fā)出警告的,但是我們分析一下,A(a)是臨時構(gòu)造了一個A對象,然后a_obj成為了這個臨時對象的引用。但是問題是,這個臨時對象在B對象構(gòu)造之后就馬上銷毀了,也就是說,a_obj引用了一個不存在的對象(換到指針說就是指向了空指針)。這是一個巨大的錯誤,將在運(yùn)行時引發(fā)錯誤。
所以,結(jié)論是:如果成員數(shù)據(jù)使用(新)對象,則必須定義這個對象所屬類的復(fù)制構(gòu)造函數(shù);如果使用的是對象引用或者指針,則一定只能用已經(jīng)存在并且會在B對象整個生命周期內(nèi)都存在的A對象來構(gòu)造這個B對象。
說得貌似很復(fù)雜,留個作為例子的3個類,大家可以多寫幾個演示程序試試。
#ifndef A_HPP
#define A_HPP
#include <iostream>
using namespace std;
char* get_point(int lenth);
void free_point(char* temp);
class A
{
private:
//
protected:
char* temp;
int lenth;
A();
public:
A(const A& copy);
~A();
void show() const;
};
class C: public A
{
public:
C(int _lenth);
~C();
};
class B
{
private:
A b;
public:
B(const A& a);
B(int _lenth);
~B();
void show() const;
};
#endif
#include "a.hpp"
A::A(): temp(0),lenth(0)
{
cout<< "A Constructor!" << endl;
}
A::A(const A& copy): lenth(copy.lenth)
{
temp = get_point(lenth);
cout << "A Copy Constructor" << endl;
cout << "temp at: " << int(temp) << endl;
}
A::~A()
{
cout << "temp at: " << int(temp) << endl;
free_point(temp);
cout << "Heap Deleted!\n";
cout << "A Destroyed!" << endl;
}
void A::show() const
{
cout << temp << endl;
}
//***************************************
C::C(int _lenth): A()
{
lenth = _lenth;
temp = get_point(lenth);
cout<< "C Constructor!" << endl;
cout << "temp at: " << int(temp) << endl;
}
C::~C()
{
cout << "C Destroyed!" << endl;
}
//***************************************
B::B(const A& a): b(a)
{
cout<< "B Constructor!" << endl;
}
B::B(int _lenth): b(C(_lenth))
{
cout<< "B Constructor!" << endl;
}
B::~B()
{
cout << "B Destroyed!" << endl;
}
void B::show() const
{
b.show();
}
//************************************
char* get_point(int lenth)
{
char* temp = new char[lenth+1];
for ( int i = 0; i< lenth; i++ )
temp[i] = '*';
temp[lenth] = '\0';
cout << "New buffer got!\n";
return temp;
}
void free_point(char* temp)
{
delete []temp;
cout << "Buffer deleted!\n";
}