2015-04-04 99 views
0

以類似的方式思考:
1.數組的裸名與指向第一個元素的指針相同,不需要指定索引0.
2.來自Java的toString()可以使用不調用任何對象方法的對象的名稱作爲字符串。有沒有辦法只使用類的對象名稱作爲「默認」成員?

現在有沒有辦法在C++中使用類對象的名稱來引用其第一個成員? 考慮:

class Program 
{ 
public: 
    int id; 
    char *str; 
}; 

void function(int p) 
{ 
//... 
} 

然後:

Program prog0; 
function(prog0); // instead of function(prog0.id) 

任何方式 「隱藏」 的成員引用?
編輯:
爲什麼holyBlackCat的答案被刪除?我傾向於將它作爲最佳答案投票 - 沒有冒犯,Mateusz。但他是第一個建議轉換操作員的人,這個例子是完整和簡單的。

+0

Java的'toString()'如何在不調用任何方法的情況下工作? – juanchopanza 2015-04-04 13:25:48

+2

數組的名稱*不等於指針。 – chris 2015-04-04 13:25:48

+0

@juanchopanza,我想如果你傳遞了一個字符串的地方,它隱式調用'.toString()'。 – chris 2015-04-04 13:26:32

回答

5

在C++中,這樣的行爲將是一場災難。如果我理解正確,Java會嘗試通過搜索A中的第一個成員,即B類型或隱式轉換爲B來將A類型的對象轉換爲B類型的對象。

C++沒有這樣設計。我們喜歡編寫代碼,這總是可以預測的。你可以達到你想要的,但是對於一個價格。

在這種情況下,最好的解決辦法是轉換操作符 - 考慮:

class Program 
{ 
public: 
    int id; 
    char *str; 

    operator int() 
    { 
    return this->id; 
    } 

    //You can have more than one! 
    operator const char*() 
    { 
    return this->str; 
    } 
}; 

void function_int(int p) 
{ 
} 

void function_str(const char* s) 
{ 
} 

現在可以做到以下幾點:

Program prog; 
function_int(prog); //Equivalent of function_int(prog.id) 
function_str(prog); //Equivalent of function_int(prog.str) 

的價格是,如果添加另一個int並將其放在id之前,它不會用於轉換,因爲我們在我們的操作員明確指出,我們班級的「int內容」由id代表,此成員是c當涉及到這樣的轉換時,我們會有所考慮。

但是,即使這個簡單的例子也顯示了一些潛在的問題 - 用整數和指針類型重載函數可能會導致非常不可預測的行爲。當type包含轉換運算符時,指針和整數都會變得更糟。

假設,我們有如下功能:

void func(unsigned long) 
{ 
} 

我們稱之爲funcProgram類型的參數。您希望調用哪個轉換運算符?編譯器知道如何將Program轉換爲intconst char*,但不是unsigned longThis article on cppreference應該可以幫助您瞭解隱式轉換的工作方式。


另外,正如Barry指出的,更無意義的結構變得可用。考慮一下:

int x = prog + 2 

這是什麼意思?不過,這是完全有效的代碼。這就是轉換運營商應該非常小心的原因(在C++ 11之前的時代,有一個普遍的建議,每個類最多隻能有一個這樣的運營商)。從MSDN

引用:

如果需要轉換引起歧義,則產生一個錯誤。如果有多個用戶定義的轉換可用或存在用戶定義的轉換和內置轉換,則會產生歧義。

有時候,簡單的解決這個問題是標記轉換運營商,明確關鍵字,所以你需要以上更改來電:

function_int((int)prog); 
function_str((const char*)prog); 

而不是像以前的形式一樣漂亮,但更安全。這基本上意味着,編譯器被禁止使用標記爲顯式的運算符執行任何隱式轉換。對於避免模糊調用非常有用,但仍然在代碼中提供了一些靈活性 - 您仍然可以非常輕鬆地將一種類型的對象轉換爲另一種類型的對象,但是您可以確定執行這些轉換的時間和位置。

但是,某些編譯器仍然不支持顯式轉換運算符,因爲這是C++ 11功能(例如,Visual C++ 11不支持它)。

您可以閱讀更多關於明確關鍵字here

+1

現在也可以執行'int x = prog + 2;',這幾乎肯定是零感。 – Barry 2015-04-04 13:58:20

+0

當然可以。這是錯誤設計的代價。隱式轉換可能是有害的。但我看到很多代碼每天都是這樣寫的。這就是爲什麼我寫這個,並解釋爲什麼**顯式**關鍵字可以幫助你提供很大的靈活性沒有這種無稽之談。我會用你的例子更新我的答案。 – 2015-04-04 14:05:15

+0

謝謝。 Java不允許任何類型的東西,我只是勾勒出一種思維方式。我希望像對象總是會連續存儲其成員,並且首先聲明的成員將始終存儲在對象的起始地址,從而利用這種方式。 – mireazma 2015-04-04 14:12:19

0

現在有沒有辦法在C++中使用類對象的名稱來引用其第一個成員?

不,C++沒有任何反射,所以沒有辦法真正確定「第一個成員」是什麼。

但是,如果你真正想要的是可以爲任何對象的ID,你可以只要求對象有一個方法:

template <typename T> 
void function(const T& t) { 
    int id = t.getID(); 
    // etc. 
} 

不知道更多關於你的使用情況,就很難知道該怎麼建議。

+0

謝謝。我編輯了問題標題,因爲你的回答讓我看到它是不正確的。該函數來自OpenGL,因此我無法修改它。 – mireazma 2015-04-04 13:52:42

+0

@mireazma可以在你的對象和OpenGL之間編寫你自己的適配器。無論是明確表示,還是傳遞'prog0.id',都沒有錯 - 走最少的驚喜之路! – Barry 2015-04-04 13:57:11

相關問題