2012-07-13 52 views
6

我有一個類(姑且稱之爲base的時刻),有一個保護的接口,包括受保護的構造等base返回由值的base比如有的功能:可視性問題

class base { 
protected: 
    base() {} 
    base (base const &other) {} // line 6 
    base foo() { 
     base ret; 
     return ret; 
    } 
}; 

這些功能被包裹在派生類返回派生類型如下所示:

class derived : public base { 
private: 
    derived(base const &b) : base(b) {} 
public: 
    derived() : base() {} 
    derived foo() { 
     derived d(base::foo()); // line 21 
     return d; 
    } 
}; 

爲了便於從base返回類型轉換爲一個derived返回類型,我在derived中提供了一個私有構造函數來處理這個問題。從

test.cpp: In member function ‘derived derived::foo()’: 
test.cpp:6: error: ‘base::base(const base&)’ is protected 
test.cpp:21: error: within this context 

用gcc 4.6.1和2.9鐺在Linux薄荷12,代碼編譯文件,甚至與-Wall -Wextra,除了:

用gcc 4.1.2在CentOS 5.8編譯此產生以下錯誤base的拷貝構造函數的unused parameter警告。

我認爲這可能是gcc 4.1.2中的一個編譯器錯誤,但我無法在網上找到任何東西。有沒有人見過這個?

我無法更新編譯器而沒有巨大的痛苦。是否有一個簡單的解決方法,而不是基本類的複製構造函數公開?


EDIT I線21之前在derived::foo()加入base b;。在這種情況下,gcc 4.6.1和gcc 4.1.2會抱怨base的默認ctor被保護,clang 2.9會在沒有警告的情況下編譯。這就是DavidRodríguez - dribeas在他的評論中說的 - 默認ctor不能在base的不同實例上調用。


EDIT 2標準款似乎適用於這裏是11.5 [class.protected。 gcc 4.1.2似乎是正確的拒絕我的代碼是不正確的,我想知道爲什麼gcc 4.6.1和clang允許它。查看我自己的答案以獲得初步解決方案。

+0

由於MarkB已經刪除了他的答案,所以我將在這裏發表主要觀點:'protected'不會給派生類型訪問這些成員在* any *實例上的成員類型。您只能訪問您自己派生類型的受保護成員。即'derived :: foo()'只能從'this'或任何其他'derived'對象(包括完全類型派生自'derived'的對象)訪問'base'的受保護成員。 – 2012-07-13 15:10:11

+0

是的,我讀到了(甚至在標準中查看),這也是我的第一個想法,但我想知道爲什麼gcc 4.6.1和clang 2.9。編譯這個沒有問題。 – arne 2012-07-13 15:11:32

+0

+1 @DavidRodríguez-dribeas大開眼界。整個過程中我一直受到錯誤的印象。不僅如此,我確實相反。 – 2012-07-13 15:24:45

回答

0

我初步的解決方案是讓base的拷貝構造函數public。要禁止使用base的副本對derived實例進行復制,則繼承需要爲protected而不是public。由此產生的類現在看起來像這樣:

class base { 
protected: 
    base() {} 
public: 
    base (base const &other) {} 
protected: 
    base foo() { 
     base ret; 
     return ret; 
    } 
}; 

class derived : protected base { 
private: 
    derived(base const &b) : base(b) {} 
public: 
    derived() : base() {} 
    derived foo() { 
     derived d(base::foo()); 
     return d; 
    } 
}; 
1

一種解決方法,你可以嘗試將涉及創建派生一個私人的構造函數,構造它通過調用基函數的基:

class derived : base { 
    struct from_base_foo {}; 
    derived(from_base_foo) : base(base::foo()) {} 
public; 
    derived foo() { 
     return derived(from_base_foo()); 
    } 
}; 
+0

試過了,這個錯誤然後會被髮送到您的新''''base''構造函數的調用中, 'derived''構造函數。 – arne 2012-07-13 15:08:48

+0

哦,它試圖將右值'base :: foo'綁定到作爲參數傳遞給'base'拷貝構造函數的const lvalue,它在初始化列表中抱怨... – 2012-07-13 15:12:12