複數類對象被賦常量的分析
一、 背景講述
在c++類中,我們通常會去實現一個複數類,複數類的對象包含複數的兩個部分,實部和虛部。通常在複數類的實現過程中會自己實現構造函數。
在使用定義的複數類定義對象時,如果我們定義的複數類的構造方法中包含以下三個:
ccomplex()
{
real = 0;
imag = 0;
}
ccomplex(double mreal)
{
real = mreal;
imag = 0;
}
ccomplex(double mreal, double mimag)
{
real = mreal;
imag = mimag;
}
則你會發現我們在定義複數對象後賦值時可以通過:
ccomplex a[4] = {ccomplex(), ccomplex(1), 2, ccomplex(3,4)};
四種方法來給對象賦值,這裏第一個明顯調用的第一個構造方法,第二個調用了第二個構造方法,第四個調用了第三個構造方法,很奇怪的是爲什麼第三個可以這樣賦值,賦值後,如果輸出複數,又會輸出什麼結果呢?
二、 代碼體現
爲解釋上述疑問,實現測試代碼如下:
#include <iostream>
using namespace std;
class ccomplex
{
private:
double real;
double imag;
public:
ccomplex()
{
real = 0;
imag = 0;
}
ccomplex(double mreal)
{
real = mreal;
imag = 0;
}
ccomplex(double mreal, double mimag)
{
real = mreal;
imag = mimag;
}
void display();
};
void ccomplex::display()
{
cout << "(" << real << ",";
cout << imag << "i)" << endl;
}
int main()
{
int i = 0;
ccomplex c[4] = {ccomplex(), ccomplex(2), 3, ccomplex(5,6)};
ccomplex a = 7;
for(i=0;i<4;i++)
{
c[i].display();
}
a.display();
return 0;
}
通過代碼測試,上述中的對ccomplex對象直接賦值3和7,是沒有錯誤的,輸出的結果如下:
(0,0i)
(2,0i)
(3,0i)
(5,6i)
(7,0i)
三、 原因分析
之所以會上述代碼沒有錯誤原因在於:
C++編譯器會爲每個定義的類A,自動生成四個缺省的函數,他們分別是:
A(void); //缺省的參數數構造函數
A(const A &a); //缺省的拷貝構造函數
~A(void); //缺省的析構函數
A & operate = (const A &a);//缺省的賦值函數
上述測試的代碼中,我們實現了構造函數,那麼其他的三個拷貝構造函數,析構函數,賦值函數則是編譯器自動添加的。
其中因爲實現了賦值函數,所以我們在給一個複數類賦值3或7時,該3或7要被轉換成一個複數類的對象。因爲3或7不是複數類對象,所以不會調用缺省的拷貝構造函數,而是調用我們自己實現的構造函數,3或7是一個數據,所以調用單個參數的構造函數
ccomplex(double mreal)
{
real = mreal;
imag = 0;
}
來實現。
所以這時3或7就被賦給了複數的實部。
因爲這種情況只有一個參數傳給構造函數,所以如果我們沒有定義這個構造方法,這種賦值方法是不可以的。