C++轉換建構函式(詳解版)

2020-07-16 10:04:42
一個建構函式接收一個不同於其類型別的形參,可以視為將其形參轉換成類的一個物件。像這樣的建構函式稱為轉換建構函式

除了建立類物件之外,轉換建構函式還為編譯器提供了執行隱式型別轉換的方法。只要在需要類的型別值的地方,給定建構函式的形參型別的值,就將由編譯器執行這種型別的轉換。

舉一個簡單的例子,先來看下面這個類:
class IntClass
{
    private:
        int value;
    public:
        //轉換int的轉換建構函式
        IntClass(int intValue)
        {
            value = intValue;
        }
        int getValue() const { return value; }
};
由於建構函式 IntClass(int) 只接收一個型別不同於 IntClass 的單個形參,所以它是一個轉換建構函式。

只要上下文需要類物件,但提供的卻是建構函式形參型別的值,則編譯器將自動呼叫轉換建構函式,這會在以下 4 種不同的上下文環境中出現:
  • 該類的一個物件使用轉換建構函式的形參型別的值進行初始化。例如:

IntClass intObject = 23;

 
  • 該類的一個物件被賦給了一個轉換建構函式形參型別的值。例如:

intObject = 24;

 
  • 函數需要的是該類的型別的值形參,但傳遞的卻是建構函式的形參型別的值。例如,假設定義了下面這樣一個函數:
void printValue(IntClass x)
{
    cout << x.getValue();
}
但是在呼叫它的時候卻傳遞了一個整數給它:

printValue(25);

編譯器將使用轉換建構函式將整數 25 轉換為 IntClass 類的物件,然後將該物件傳遞給該函數。如果形參是一個指標或對 IntClass 物件的參照,則編譯器將不會呼叫轉換建構函式。只有在形參按值傳遞時,才會呼叫轉換建構函式。

  • 宣告類的型別的返回值的函數實際上返回的卻是轉換建構函式的形參型別的值。例如,編譯器將接收以下函數:
IntClass f(int intValue)
{
    return intValue;
}
請注意,雖然已經將 IntClass 宣告為其返回型別,但是該函數仍然會返回整數型別的值,於是編譯器也將再次隱式地呼叫轉換建構函式,將整數 intValue 轉換為一個 IntClass 物件,這個物件正是需要從函數返回的物件。

以下程式演示了轉換建構函式的操作。
Convert.h的內容
#include <iostream>
using namespace std;

class IntClsss
{
    private:
        int value;
    public:
        //Convert constructor from int
        IntClass(int intValue)
        {
            value = intValue;
        }
        int getValue() const { return value; }
};

//Convert.cpp 的內容
#include "Convert.h"
IntClass f(int intValue)
{
    return intValue;
}
void printValue(IntClass x)
{
    cout << x.getValue();
}
//mian函數
//This program demonstrates the action of convert constructors.
#include "Convert.h"
// Function prototypes.
void printValue (IntClass);
IntClass f(int);
int main()
{
    // Initialize with an int
    IntClass intObject = 23;
    cout << "The value is " << intObject.getValue() << endl;
    // Assign an int
    intObject = 24;
    cout << "The value is " << intObject.getValue() << endl;
    //Pass an int to a function expecting IntClass
    cout << "The value is ";
    printValue(25);
    cout << endl;
    // Demonstrate conversion on a return
    intObject = f(26);
    cout << "The value is ";
    printValue(intObject);
    return 0;
}
程式輸出結果:

The value is 23
The value is 24
The value is 25
The value is 26

只要從某些型別自動轉換為類的型別是有意義的,那麼就應該考慮使用一個轉換建構函式。在 C++ string 類中可以找到使用轉換建構函式的實用範例。string 類提供一個將 C 字串轉換為 string 的轉換建構函式:
class string
{
    //僅顯示轉換建構函式
    public:
        string(char *);
};
該轉換建構函式的存在允許程式設計師將 C 字串傳遞給需要 string 物件形參的函數,將 C 字串賦值給 string 物件,並使用 C 字串作為 string 物件的初始值:
string str = "Hello";
str = "Hello There!";
在某種意義上,轉換建構函式的工作方式與前面介紹的型別轉換運算子剛好相反:型別轉換運算子是將一個物件轉換為其他型別的值,而轉換建構函式則是將給定型別的值轉換為類的物件。