What I want to do : a simple storage class, defined as a template to be as general as possible. And being able to derive from this class another, that would accept anything, convert it to int
(the algorithm is not relevant here), and store it in the underlying class.
我想做的是:一个简单的存储类,定义为尽可能一般化的模板。并且能够从这个类中派生出另一个,可以接受任何东西,将它转换为int(该算法在这里不相关),并将其存储在底层类中。
But, this doesn't quite work as expected. Here is the minimal test case I wrote:
但是,这并不像预期的那样有效。下面是我写的最小测试用例:
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;
}
Of course, this doesn't work:
当然,这是行不通的:
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)
Is there any way to force the compiler to use the method definition from the B class, or is this a really bad idea?
有没有办法强迫编译器使用B类的方法定义,或者这真的是个坏主意吗?
--
- - -
Edit: Made the inheritance public.
编辑:使继承公开。
2 个解决方案
#1
3
First off, as @GermanDiago pointed out, you're using private inheritance, so you're getting the "base class inaccessible" error. Change B
to derive from A<int>
publically.
首先,正如@GermanDiago指出的那样,您使用的是私有继承,因此您得到了“基类不可访问”的错误。更改B从公共的
Even so, this won't fix the issue. Name lookup is based on static types. When you have a pointer to A<int>
, accessing members through that pointer will only look at the members of A<int>
.
即便如此,这也不能解决问题。名称查找基于静态类型。当您有一个指向
You have to access through type B
to see B
's members:
你必须通过B类才能看到B的成员:
int main() {
B* ptr = new B;
ptr->f("foo");
delete ptr;
return 0;
}
Of course, if I understand your question correctly, this is not what you really want. You might look at the Curiously Recurring Template Pattern instead.
当然,如果我正确理解了你的问题,这不是你真正想要的。您可能会看到奇怪的重复的模板模式。
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;
}
生活的例子
Of course, this has the downside of B
becoming part of A
's type. I don't think there's a way out of this while still remaining compile-time.
当然,这是B成为A的一部分的缺点。我不认为有什么办法可以解决这个问题。
#2
1
You must use public inheritance:
您必须使用公共继承:
class B : public A<int> {
//...
}
is-a relationship in c++ is through public inheritance. Private inheritance is what you are currently using.
在c++中的关系是通过公共继承的。私有继承是当前使用的。
#1
3
First off, as @GermanDiago pointed out, you're using private inheritance, so you're getting the "base class inaccessible" error. Change B
to derive from A<int>
publically.
首先,正如@GermanDiago指出的那样,您使用的是私有继承,因此您得到了“基类不可访问”的错误。更改B从公共的
Even so, this won't fix the issue. Name lookup is based on static types. When you have a pointer to A<int>
, accessing members through that pointer will only look at the members of A<int>
.
即便如此,这也不能解决问题。名称查找基于静态类型。当您有一个指向
You have to access through type B
to see B
's members:
你必须通过B类才能看到B的成员:
int main() {
B* ptr = new B;
ptr->f("foo");
delete ptr;
return 0;
}
Of course, if I understand your question correctly, this is not what you really want. You might look at the Curiously Recurring Template Pattern instead.
当然,如果我正确理解了你的问题,这不是你真正想要的。您可能会看到奇怪的重复的模板模式。
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;
}
生活的例子
Of course, this has the downside of B
becoming part of A
's type. I don't think there's a way out of this while still remaining compile-time.
当然,这是B成为A的一部分的缺点。我不认为有什么办法可以解决这个问题。
#2
1
You must use public inheritance:
您必须使用公共继承:
class B : public A<int> {
//...
}
is-a relationship in c++ is through public inheritance. Private inheritance is what you are currently using.
在c++中的关系是通过公共继承的。私有继承是当前使用的。