2015-02-06 29 views
5

我想有一個類,它允許訪問它的基本情況的const接口,但不是。特別是:應該將運算符const Base&()用於不可訪問的基類嗎?

class B 
{}; 

class A : private class B 
{ 
public: 
    operator const B&() { return *this; } 
}; 

int main() 
{ 
    A a; 
    const B& b = a; // Should this line be an error? 
} 

g ++給出了無法訪問的基類錯誤。你有沒有語言專家認爲這個錯誤在C++ 11/C++ 14中是正確的?

是的,我知道我可以(而且會)只是這樣做:

int main() 
{ 
    A a; 
    const B& b = a.operator const B&(); 
} 

對這種結構的另一種方法有什麼建議?

+0

你已經有答案說明這是一個錯誤,但也想想看會發生什麼,如果它不是一個錯誤:它將意味着'const B&b = a;'具有完全不同的行爲,取決於它是否出現在'A'的'朋友'。 – hvd 2015-02-06 17:42:38

+0

爲什麼不只是組合而不是私有繼承? – 2015-02-06 17:49:12

回答

5

[dcl.init.ref]/5:

A reference to type 「cv1T1 」 is initialized by an expression of type 「cv2T2 」 as follows:

  • If the reference is an lvalue reference and the initializer expression

    • is an lvalue (but is not a bit-field), and 「cv1T1 」 is reference-compatible with 「cv2T2 ,」 or
    • has a class type (i.e., T2 is a class type), where T1 is not reference-related to T2, [..]

    then the reference is bound to the initializer expression lvalue in the first case and to the lvalue result of the conversion in the second case (or, in either case, to the appropriate base class subobject of the object).

轉換函數將被覆蓋在所述第二項目符號點。然而,即使它是私有基類,B與(並與之兼容)A也是引用相關的,因此第一個要點適用。現在[dcl.init.ref/4定義這種情況下是非法的構造:

Given types 「cv1T1 」 and 「cv1T2 」, 「cv1T1 」 is reference-related to 「cv1T2 」 if T1 is the same type as T2 , or T1 is a base class of T2 . 「cv1T1 」 is reference-compatible with 「cv2T2 」 if T1 is reference-related to T2 and cv1 is the same cv-qualification as, or greater cv-qualification than, cv2. In all cases where the reference-related or reference-compatible relationship of two types is used to establish the validity of a reference binding, and T1 is a base class of T2 , a program that necessitates such a binding is ill-formed if T1 is an inaccessible [..] base class of T2.

這種參考綁定將因此總是失敗,不管可用的任何轉換函數。引用綁定不能用於私有繼承。

您的顯式調用是解決此問題的方法,但不再需要轉換操作符:只需定義一個返回const-引用的getter即可。例如。

const B& b = a.getB(); 
3
const B& b = a; 

不調用A::operator const B&()。這種行爲自C++ 03天以來就存在。
這是一個簡單的上傳發生從派生類型到基本類型。此向上投射會引發編譯器錯誤,因爲基地(class B)由全局範圍內派生(class A)私下繼承。

如果BA之間沒有這種繼承關係,那麼肯定會提到operator const B&()將根據您的期望實例化。

2

錯誤是正確的。只有類型與參考無關時,纔會考慮隱式轉換(在本例中,通過您的運算符)。繼承關係意味着它們是,所以引用將直接綁定而不用轉換,但由於私有繼承而失敗。

除非您有充分的繼承理由,否則您可以使A成爲成員而不是基類。在這種情況下,返回對該成員的引用的轉換運算符將執行您想要的操作。

如果你確實需要繼承,那麼一個適當命名的函數可能比需要明確的操作符調用更好。

相關問題