2013-04-28 106 views
1

我得到一個C++編譯器錯誤,我不明白並且一直找不到 修復或解釋。這是一個演示問題的代碼片段。繼承的模板類中的C++編譯器錯誤

#include <iostream> 

template<class T> 
class A { 
public: 
    A(int n) {data = new T[n]; } 
    const T &operator()(int i) const {return data[i];} 
protected: 
    T *data; 
}; 

template<class T> 
class B : public A<T> { 
public: 
    B(int n) : A<T>(n) {} 
    T &operator()(int i) {return this->data[i]; } 
    //const T &operator()(int i) const {return this->data[i];} // fixes problem 
}; 

template<class T, int N> 
class C : public B<T> { 
public: 
    C() : B<T>(N) {} 
private: 
}; 

template<class T> 
void doOp(const T &v) { 
    std::cout << v(0) << std::endl; 
} 

void templateTest() 
{ 
    C<double, 3> c; 
    c(0) = 5; 
    std::cout << c(0) << std::endl; 

    doOp(c); 
} 

如果我取消註釋中的B類線,代碼編譯並執行正確,但我 不明白,爲什麼在定義B級這個操作符的功能是任何不同 類A的定義

感謝您的幫助。

比爾

+2

,什麼是錯誤訊息?你不認爲這可能有關嗎? – 2013-04-28 13:12:43

回答

2

的問題是,doOp()通過到const一個引用調用非const成員函數。

如果取消對註釋行的註釋,將找到一個可行的const成員函數,重載解析將選擇該版本的調用操作符。

如果不取消註釋該行,則找不到該調用操作符的繼承版本,因爲它是由子類中的重載調用操作符隱藏隱藏

爲了說明的名字用簡單的例子隱瞞問題,請考慮以下方案:

struct X 
{ 
    void foo() { } 
}; 

struct Y : X 
{ 
    void foo(int) { } 
}; 

int main() 
{ 
    Y y; 
    y.foo(42); // OK 
    y.foo(); // ERROR! Name hiding... 
} 

這裏的編譯器將不能夠解決調用y.foo(),因爲X::foo()正在Y::foo()隱藏這裏。

爲了解決這個問題,你可以在Y添加using聲明:

struct X 
{ 
    void foo() { } 
}; 

struct Y : X 
{ 
    using X::foo; 
// ^^^^^^^^^^^^^ 

    void foo(int) { } 
}; 

int main() 
{ 
    Y y; 
    y.foo(42); // OK 
    y.foo(); // OK 
} 

現在,這兩個函數調用正確解析。在你的程序中,你可以添加一個類似using聲明的基類的operator()

template<class T> 
class B : public A<T> { 
public: 
    B(int n) : A<T>(n) {} 
    T &operator()(int i) {return this->data[i]; } 

    using A<T>::operator(); 
// ^^^^^^^^^^^^^^^^^^^^^^^ 
}; 
+0

非常感謝這個簡單的例子和​​修復!我顯然已經忘記了隱藏基類中的重載函數。但是當你指出我的意思後,我發現這種行爲在例如李普曼的書。 ;-(再次感謝您的幫助Bill Bill – 2013-04-28 13:52:12

+0

@BillGreene:很高興幫助:)如果這能解決您的問題,請考慮將答案標記爲已接受 – 2013-04-28 13:54:22