![](/img/trans.png)
[英]How does operator overload resolution work in the presence of the new initializer sequence?
[英]How does the assignment operator overload resolution work in this example? The result is unexpected for me
這是我不理解的代碼:
class Base
{
public:
Base(){}
Base operator=(Base ob2)
{
std::cout << "Using Base operator=() " << '\n';
return *this;
}
};
class Derived : public Base
{
public:
Derived(){}
Derived operator=(Base ob2)
{
std::cout << "Using Derived operator=() " << '\n';
return *this;
}
};
int main()
{
Derived derived1, derived2;
Base base1;
derived1 = derived2; // Uses base operator=()
derived1 = base1; // Uses derived operator=()
return 0;
}
確定的第一個賦值使用Base類的運算符,第二個賦值使用Derived類的運算符的語言規則是什么?
是的,我知道通常不會像這樣聲明賦值運算符。 這就是為什么我稱它為accademical。
短版本 :重載分辨率沒有選擇Base::operator=(Base)
。 它選擇了隱式聲明的Derived::operator=(const Derived &)
,它調用Base::operator=(Base)
來復制 - 賦值基類子對象。
帶標准報價的長版 :
首先,復制賦值運算符在§12.8[class.copy] / p17中的標准中定義:
用戶聲明的復制賦值運算符
X::operator=
是類X的非靜態非模板成員函數,其中只有一個參數類型為X
,X&
,const X&
,volatile X&
或const volatile X&
。
其次,如果您不提供復制賦值運算符,將始終為您隱式聲明一個。 來自§12.8[class.copy] / p18:
如果類定義未顯式聲明復制賦值運算符,則會隱式聲明一個。 如果類定義聲明了移動構造函數或移動賦值運算符,則隱式聲明的復制賦值運算符被定義為已刪除; 否則,它被定義為默認值(8.4)。 如果類具有用戶聲明的復制構造函數或用戶聲明的析構函數,則不推薦使用后一種情況。 類X的隱式聲明的復制賦值運算符將具有該表單
X& X::operator=(const X&)
如果
X
每個直接基類B
都有一個復制賦值運算符,其參數類型為const B&
,const volatile B&
或B
,和- 對於類型為M(或其數組)的
X
所有非靜態數據成員,每個這樣的類類型都有一個復制賦值運算符,其參數類型為const M&
,const volatile M&
或M
否則,隱式聲明的復制賦值運算符將具有該表單
X& X::operator=(X&)
請注意,這些規則的結果之一是(§12.8[class.copy] / p24):
因為如果未由用戶聲明,則為類隱式聲明復制/移動賦值運算符,則基類復制/移動賦值運算符始終由派生類的相應賦值運算符隱藏。
換句話說,重載決策永遠不能為從一個Derived
到另一個Derived
的賦值選擇Base
的復制賦值運算符。 它始終是隱藏的,甚至不在候選函數集中。
最后,§12.8[class.copy] / p28提供了這一點
非聯合類X的隱式定義的復制/移動賦值運算符執行其子對象的成員復制/移動分配。
在問題的情況下,沒有為Derived
提供復制賦值運算符,因此將隱式聲明一個默認值(因為Derived
沒有用戶聲明的移動構造函數或移動賦值運算符)。 此隱式復制賦值運算符將通過重載決策選擇,並執行基類子對象的復制賦值,該對象調用為Base
定義的復制賦值運算符。
創建類時,編譯器會隱式生成以下函數(除非您明確指定其中一些函數,請參閱http://en.wikipedia.org/wiki/Special_member_functions ):
在您的情況下,復制賦值操作員簽名是:
struct Foo {
Foo &operator=( const Foo &f ); // either this
Foo &operator=( Foo f ); // does not make much sense but will work too
};
為Derived
類創建賦值運算符時,不會顯式替換隱式副本賦值運算符,而是創建一個新運算符。 要更輕松地了解此問題,請將代碼修改為:
class Derived : public Base
{
public:
Derived(){}
Derived &operator=(const Base &ob2)
{
std::cout << "Using Derived operator=(Base) " << '\n';
return *this;
}
Derived &operator=(const Derived &ob2)
{
std::cout << "Using Derived operator=(Derived) " << '\n';
return *this;
}
};
問題應該變得明顯。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.