考虑代码:
#include <iostream>
class A {
public:
void g() {std::cout << "Call from A" << std::endl;}
void f() {g();}
};
class B : public A {
public:
void g() {std::cout << "Call from B" << std::endl;}
};
int main() {
B b;
b.f(); // "Call from A"
}
如果我将A::g()
设为虚拟,则输出“来自B的呼叫”。
当我们希望接口允许多态时,我总是理解“虚拟”很有用,比如说A *a = new B(); a->f()
,但是这个例子表明在这种情况下也需要virtual
。我对此示例的理解是g()
上的A::f
调用正式等同于this->g()
,这是一个指针。
然而,这不是我真正想要的:在我的真实示例中,我有一个通用模板类A,其中包含一般方法A::simulate
(比如A::f
),它使用不同的方法(比如说{ {1}}),其中一些被子类覆盖(比如A::g()
)。我想要的是让方法B
以这样的方式将代码编译在A的子类中,就像它已经在子类上定义一样,所以我没有多次相同的逻辑编码。我怎么能这样做?
这是因为我的界面不需要多态,因为用户总是需要编译代码(即它只是标题)。
答案 0 :(得分:11)
你可以简单地让你的基类为CRTP(正如你所提到的那样,它已经是一个模板化的类):
#include <iostream>
template<class Derived>
class A {
public:
void g() {std::cout << "Call from A" << std::endl;}
void f() { static_cast<Derived*>(this)->g();}
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Call g() from Derived
};
class B : public A<B> {
public:
void g() {std::cout << "Call from B" << std::endl;}
};
int main() {
B b;
b.f(); // "Call from B"
}