从模板化类重写纯虚拟函数

Overriding a pure virtual function from templated classes

本文关键字:虚拟 函数 重写      更新时间:2023-10-16

我已经搜索了堆栈溢出,但没有找到确切的答案。我有一个接口类,它只包含纯虚拟函数,我希望由派生自该类的类来实现这些函数。

我有一个接口,我将调用BaseInterface,它定义了我希望在从该接口派生的所有类中重写的函数。在本例中,假设只有一个名为toImplement的纯虚拟函数。我创建了一个名为Base的类,该类继承自BaseInterface,并为继承的纯虚拟函数添加了一些功能。Base仍然是一个抽象类,因为它没有实现BaseInterface中的函数。

我有几个从Base派生的类,它们都受益于Base的通用功能,但指定在它们的实例上运行toImplement时会发生什么。这些类都应该是具体的,并满足BaseInterface设置的所有要求。下面我定义了其中一个类,称为Derived

当BaseInterface和Base未被模板化时,所有这些都可以正常工作。代码编译和运行良好,无需在Base中定义(1.)或实现(2.)toImplement

但是,我希望toImplement能够使用不同的类型。据我所知,在模板化的类中拥有纯虚拟函数是可以的。我在某些类型T上模板BaseInterfaceBase。当我没有在Base(1.)中定义to Implement时,我无法编译,因为Base不知道在tryUsingImplemented中使用哪个toImplement。如果我现在将定义添加到Base,代码会预编译,但链接器找不到Base::toImplement的实现。最后,如果我在Base(1。和2.),代码编译。

我不喜欢这样,因为我在Base中有一个toImplement的伪实现,我从不希望运行这个实现。此外,由于Base实现了toImplement,因此不再需要Derived来实现它。这使得BaseInterface在我看来毫无用处。

Sobody能告诉我如何在Derived中强制执行toImplement,而不必首先在Base实现它吗?

template <typename T>
class BaseInterface {
virtual void toImplement(T & t) = 0;
};

template <typename T>
class Base : public BaseInterface<T> {
bool m_useImplemented;
public:
explicit Base(bool useImplemented) : m_usedImplemented(useImplemented) {}
void tryUsingImplemented(T & t) {
if (m_useImplemented)
toImplement(t);
}  
protected:
// 1: Defining toImplement pure virtual function in Base
virtual void toImplement(T & t);
};
// 2. Implementing a version of toImplement in Base which does nothing
template <typename T>
inline void Base<T>::toImplement(T & t) {
// do nothing
}
class Derived : public Base<int> {
public:
explicit Derived(bool useImplemented) : Base<int>(useImplemented) {}
protected:
// 3. implementing toImplement in Derived 
void toImplement(T & t) {
std::cout << "Doing stuff for Derived" << std::endl;
}  
};

为了便于将来参考,如果您提供编译器错误消息,将会很有帮助。

然而,在这种情况下,我知道。您的代码中有两个错误:

  1. toImplementBaseInterface中是私有的
  2. tryUsingImplemented中的查找不会在基类中查找。您正面临在依赖基中查找的问题。要修复它,请编写this->toImplement(t)

如果要从派生类调用toImplement,则需要在BaseInterface中将其声明为protected。我已经从派生类中删除了所有重写方法,并用int替换了参数类型Derived::toImplement,它编译得很好。后者是必要的,因为Derived不是模板,所以需要使用传递给Base的模板参数。

#include <iostream>
template <typename T>
class BaseInterface {
protected:
virtual void toImplement(T & t) = 0;
};

template <typename T>
class Base : public BaseInterface<T> {
bool m_useImplemented;
public:
explicit Base(bool useImplemented) : m_useImplemented(useImplemented) {}
void tryUsingImplemented(T & t) {
if (m_useImplemented)
toImplement(t);
}  
};
class Derived : public Base<int> {
public:
explicit Derived(bool useImplemented) : Base<int>(useImplemented) {}
protected:
// 3. implementing toImplement in Derived 
void toImplement(int & t) {
std::cout << "Doing stuff for Derived" << std::endl;
}  
};