2016-11-09 21 views
1

我很困惑,如果這很明顯,我很抱歉。我錯了,在以下內容:爲什麼當我分配該類的兩個對象時,我的構造函數被調用?

struct MyStruct 
    { 
     MyStruct(){}; 
     MyStruct(MyStruct* arg){}; 
    } 

MyStruct(MyStruct * arg){};是一個構造函數將一個指針指向一個MyStruct作爲參數?

因爲我有一個問題,當我這樣做此構造函數(我認爲這是)被稱爲:

int main() 
{ 
    MyStruct obj; 
    MyStruct* objPtr; 
    obj = objPtr; 

    return 0; 
} 

何時objPtr分配OBJ我預計編譯器抱怨,但它不」 t,而是調用MyStruct(MyStruct * arg);我認爲這是一個帶指針參數的構造函數。

任何幫助,將不勝感激。另外,如果我向該類添加複製賦值運算符,它仍然會發生。

編輯:謝謝你的答案。它看起來像我有一些閱讀要做到這一點,這個話題似乎(任何人想知道)在C++中轉換構造函數。另外我猜猜明確的關鍵字。下面是一個SO問題一個鏈接,解釋它:

What is a converting constructor in C++ ? What is it for?

回答

6
  1. 編譯器合成一個賦值操作符爲您提供:

    MyStruct& MyStruct::operator=(MyStruct const&) = default; 
    
  2. 當它看到的分配,它找到一個運營商的候選人(這是它創建的)。然後它會看到它可以使用您的構造函數進行轉換,轉換爲允許賦值的類型(MyStruct)。所以它歸結爲:

    obj = MyStruct (objPtr); 
    

如果你想看到的錯誤發生,標記你構造函數明確:

struct MyStruct 
{ 
    MyStruct(){}; 
    explicit MyStruct(MyStruct* arg){}; 
} 
+0

也許註釋,如果非默認構造函數是'顯式的',這不會發生。 - 哦!你剛剛做到了! –

+1

@MartinBonner,你的意思是我剛添加的那個? – StoryTeller

+0

這很混亂。因此,編譯器認爲賦值運算符接受一個MyStruct的引用,並且它看到一個指針,而不是說它是不匹配,而是在等號後面用指針作爲構造函數的參數構造一個新對象。這很混亂。這是正常的嗎?我有權混淆嗎?這個東西有一個特殊的名字,所以我可以查看它?哇。謝謝。 – Zebrafish

1

對於obj = objPtr;時,編譯器將嘗試調用MyStruct::operator=()obj與參數objPtr,這是MyStruct*。有一個候選人,隱式聲明的複製賦值運算符MyStruct::operator=(const MyStruct&)MyStruct可以通過轉換器構造函數MyStruct::MyStruct(MyStruct*)MyStruct*轉換,所以它編譯。

如果你製作MyStruct::MyStruct(MyStruct*)explicit,編譯將失敗。

struct MyStruct 
{ 
    MyStruct(){}; 
    explicit MyStruct(MyStruct* arg){}; 
}; 
1

當你sasign objPtrobj,你要指定MyStruct*類型的值MyStruct - 這是無效的。但是,由於您的構造函數需要MyStruct*,因此調用它來轉換該值。它基本上是一個隱式轉換:)

+0

謝謝。我認爲它的要點。我的理解是,它看到賦值運算符接受對結構的引用,並且當它看到指向結構的指針時,它會創建該結構的全新對象,將指針傳遞給構造函數並將其放在等號後面。我對此很困惑。當你說它調用單指針參數構造函數來「轉換」這個值的時候,將指針解除引用來「轉換」它會更有意義嗎?我的意思是,創建一個你沒有指定的全新對象似乎很違反直覺。 – Zebrafish

+0

@TitoneMaurice不完全。在左邊,你有一個'MyStruct' - 不是引用,只是一個值。在右邊,你有'MyStruct *'。 'MyStruct *'不是*'MyStruct'。如果你沒有構造函數,你可以做一些像'obj = * objPtr'(這當然會導致你的示例中的未定義行爲)。指向A的指針不是A,它是一個指針。您提供了一個隱式轉換運算符,因此編譯器使用它。這就是隱式轉換操作符的用途。如果你沒有提供它,你會得到一個編譯器錯誤 - 再次,你試圖分配一個指向*不同類型*的指針。 – Luaan

1
obj = objPtr; 

會打電話的

obj.MyStruct::operator =(MyStruct(objPtr)); 

標記您的構造explicit避免這類不必要的轉換。

+0

你有沒有這樣的例子,使行爲看起來有幫助?我很好奇語言開發人員在想什麼。 –

+0

@TheNate聽起來很像我典型的OOP。如果有一個採用A並返回B的默認方法,並且您有一個A的實例並且需要一個B的實例,則會調用默認方法。僅僅因爲C++(以及大多數其他語言)調用默認方法,構造函數並沒有特別說明。這並不像C++的設計者必須做出有意識的決定 - 這是SmallTalk中的一個標準,並且C++受SmallTalk的影響不小。 ML語言今天也使用它(例如F#的'None'作爲'Option None'的快捷鍵)。 – Luaan

相關問題