我想做什么:一个简单的存储类,定义为尽可能通用的模板。并且能够从另一个派生出另一个,接受任何东西,将其转换为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类中的方法定义,或者这是真的坏主意?
-
修改:将继承公之于众。
答案 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;
}
当然,这有B
成为A
类型一部分的缺点。
答案 1 :(得分:1)
您必须使用公共继承:
class B : public A<int> {
//...
}
是c ++中的关系是通过公共继承。私有继承就是你目前正在使用的。