多态性和具有不同签名的重载函数

时间:2013-10-09 09:40:18

标签: c++ class templates polymorphism

我想做什么:一个简单的存储类,定义为尽可能通用的模板。并且能够从另一个派生出另一个,接受任何东西,将其转换为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类中的方法定义,或者这是真的坏主意?

-

修改:将继承公之于众。

2 个答案:

答案 0 :(得分:3)

首先,正如@GermanDiago指出的那样,你正在使用私有继承,所以你得到了“基类无法访问”的错误。将B更改为从A<int>公开派生。

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

您必须通过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;
}

Live example

当然,这有B成为A类型一部分的缺点。

,我认为还有一种方法可以解决这个问题。

答案 1 :(得分:1)

您必须使用公共继承:

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

是c ++中的关系是通过公共继承。私有继承就是你目前正在使用的。