2012-09-13 111 views
4

考慮下面的一段代碼。具有相同名稱的C++常量和可變函數

#include <iostream> 
using namespace std; 

class Object 
{ 
public: 
Object() {} 

void Print() const 
{ 
cout << "const" << endl; 
} 

void Print() 
{ 
cout << "mutable" << endl; 
} 
}; 

void print_obj(const Object& obj) 
{ 
obj.Print(); 
} 

int main() 
{ 
Object  obj1; 
const Object obj2; 
Object*const pobj1 = &obj1; 

print_obj(obj1); 
print_obj(obj2); 

obj1.Print(); 
obj2.Print(); 

pobj1->Print(); 

return 0; 
} 

輸出是

const 
const 
mutable 
const 
mutable 

我想知道,如何C++決定調用哪個方法,具有相同的名稱面臨着許多可變的方法是什麼時候?

+1

我希望你從這個帶走的真正的答案是「我永遠不會做任何不正當的事情 - 即使我*可以*擺脫它。」 ;) – paulsm4

回答

7
print_obj(obj1); 
print_obj(obj2); 

被調用的函數傳遞的對象的CV-限定符const/volatile)的基礎上進行評價。請注意,cv-qualifiers被視爲功能重載解析。
如果傳遞對象爲const,則選擇接收const參數的函數。如果傳遞對象爲非常量,則選擇接收非常量參數的函數。


obj1.Print(); 
obj2.Print(); 
pobj1->Print(); 

如果對象是const則僅調用const成員函數可以被調用。
如果對象是非const的,那麼non-const版本將在const版本上進行預覽。

規則由標準明確規定。

參考:
C++ 03標準:
§13.3.1候選函數和參數列表:

對於非靜態成員函數,隱含的對象參數的類型是「參考cv X「,其中X是函數是其成員的類,cv是成員函數聲明中的cv限定。 [例如:對於X類的const成員函數,假定額外參數的類型爲「對const X的引用」。 ]

所以,如果該對象是const編譯器將選擇哪個具有類型的參考隱式對象參數爲const Object這是Print() const版本的成員函數的版本。

+0

C++ 11標準以與預期相同的方式將其擴展爲右值引用隱式對象參數。 –

-2

如果兩者都可以,它會更喜歡const方法到非const。

同樣適用於易失性,順便說一句。

1

所有函數重載的工作原理都是一樣的。

當考慮重載的成員函數時,它包含隱含的this參數。如果函數被聲明爲const,那麼this參數是const Object *。如果函數不是const那麼this參數是Object *。由於const限定符影響函數重載規則,這意味着函數的const也影響函數重載規則。

在你的具體的例子,print_obj(obj1)打印const因爲print_obj()被聲明爲採取const Object&,這意味着它會一直調用const版本的Print()。與一樣的東西。

obj1.Print()打印mutable因爲obj1const,因此非const版本的Print()是更好的匹配,並欽點爲函數重載解析。

obj2.Print()打印const因爲obj2const,因此const版本的Print()是唯一的函數重載這是合適的。

pobj1->Print()打印mutable因爲*pboj1是非const值,因此非const版本的Print()被拾取爲函數重載解析。

去想它最簡單的方法是,會發生什麼,如果你只是腦子裏想的

void Print(Object &obj); 
void Print(const Object &obj); 
1

飼養,對於一個正常的對象,如果非const版本可用,則非const版本選擇;否則選擇const版本。下面是分析:

print_obj(obj1); // print_obj() receives const argument, so `const` is chosen 
print_obj(obj2); // same as above 

obj1.Print(); // obj1 is not const, so non-const version is chosen 
obj2.Print(); // obj2 is const, so must choose const version 

pobj1->Print(); // pobj1 is a const pointer pointing to non-const object, so non-const version is chosen 
相關問題