1

I'm getting a C++ compiler error that I don't understand and haven't been able to find a fix or an explanation for. Here is a code snippet demonstrating the problem.

#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);
}

If I un-comment the line in class B, the code compiles and executes correctly but I don't understand why defining this operator function in class B is any different from the definition in class A.

Thanks for the help.

Bill

4

1 回答 1

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()

要解决此问题,您可以using在以下位置添加声明Y

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();
//  ^^^^^^^^^^^^^^^^^^^^^^^
};
于 2013-04-28T13:14:43.713 回答