假設我們有一個類A,另外一個類B中有個成員數據是A的對象,我們如何來定義這個成員數據呢?
最直接的,我們可以就把它定義為A的對象:A a_obj;
其次,我們可以把它定義為A對象的引用:A& a_obj; 或者const引用:const A& a_obj;
再者,我們還可以把它定義為A對象的指針:A* pA_obj; 或者const對象的指針:const A* pA_obj;
當我們直接使用A對象的時候,a_obj會在B對象建立的時候建立,在B銷毀的時候銷毀。因為這是一個新建立的對象,所以在成員初始化的時候是真正構造了對象,即我們前面說到的使用了復制構造函數。
如果使用的是A對象的引用或者指針,a_obj(或pA_obj)都沒有構造新的對象。我們假設B的一個構造函數是這樣的:B(const A& a_obj): a_obj(a_obj) {},那么毫無疑問,這個構造函數是能正常工作的,也就是說,我們用現成的對象,或者說是在B對象生命周期內都會一直存在的A對象去構造B對象是沒有問題的。但是,如果一個構造函數是這樣的:B(int a): a_obj(A(a)) {},這個函數,一般在編譯的時候是不會報錯或者發出警告的,但是我們分析一下,A(a)是臨時構造了一個A對象,然后a_obj成為了這個臨時對象的引用。但是問題是,這個臨時對象在B對象構造之后就馬上銷毀了,也就是說,a_obj引用了一個不存在的對象(換到指針說就是指向了空指針)。這是一個巨大的錯誤,將在運行時引發錯誤。
所以,結論是:如果成員數據使用(新)對象,則必須定義這個對象所屬類的復制構造函數;如果使用的是對象引用或者指針,則一定只能用已經存在并且會在B對象整個生命周期內都存在的A對象來構造這個B對象。
說得貌似很復雜,留個作為例子的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";
}
posted on 2008-04-14 12:36
lf426 閱讀(521)
評論(0) 編輯 收藏 引用 所屬分類:
語言基礎、數據結構與算法