1

我想做的:一个简单的存储类,定义为尽可能通用的模板。并且能够从这个类派生另一个,它可以接受任何东西,将其转换为int(算法在这里不相关),并将其存储在基础类中。

但是,这并不像预期的那样工作。这是我写的最小测试用例:

template<typename T>
class A {
  public:
    void f(T& foo) { }
};

class B : public A<int> {
  public:
    template<typename T>
    void f(T& foo) { }
};

int main() {
  A<int>* ptr = new B;
  ptr->f("foo");
  delete ptr;
  return 0;
}

当然,这不起作用:

pierre@raringbeast:~/Workspace/Test/src$ icpc -o Test Test.cpp 
Test.cpp(16): error: a reference of type "int &" (not const-qualified) cannot
be initialized with a value of type "const char [4]"
    ptr->f("foo");
           ^

compilation aborted for Test.cpp (code 2)

有没有办法强制编译器使用 B 类中的方法定义,或者这是一个非常糟糕的主意?

--

编辑:公开继承。

4

2 回答 2

3

首先,正如@GermanDiago 指出的那样,您使用的是私有继承,因此您会收到“无法访问基类”错误。更改BA<int>公开派生。

即便如此,这也不能解决问题。名称查找基于静态类型。当您有指向 的指针时A<int>,通过该指针访问成员只会查看 的成员A<int>

您必须通过 type 访问B才能查看B的成员:

int main() {
  B* ptr = new B;
  ptr->f("foo");
  delete ptr;
  return 0;
}

当然,如果我正确理解你的问题,这不是你真正想要的。您可能会改为查看Curiously Recurring Template Pattern

template <class T, class Derived>
class A {
  public:
    template <class U>
    void f(U& bar) {
      static_cast<Derived*>(this)->f(bar);
    }

    void f(T& foo) {

    }
};


class B : public A<int, B>
{
  public:
    template <class T>
    void f(T &foo) {
      //will be called from A's f(U&)
    }
};


int main() {
  A<int, B>* ptr = new B;
  ptr->f("foo");
  delete ptr;
  return 0;
}

活生生的例子

当然,这有B成为A's 类型的一部分的缺点。我认为在仍然保留编译时间的同时没有办法解决这个问题。

于 2013-10-09T09:54:59.210 回答
1

您必须使用公共继承:

class B : public A<int> {
    //...
}

C++ 中的 is-a 关系是通过公共继承实现的。私有继承是您当前使用的。

于 2013-10-09T09:44:46.163 回答