我正在编写一个提供公共
update()
方法的基类。当有人从这个基类派生时,他们必须实现一个纯虚拟方法来控制此更新的一小部分行为。这意味着 a.) update()
需要是公共的,b.) update()
需要调用派生类中的纯虚方法(为了安全起见,我将其设为私有)。
但是,我刚刚意识到编写派生类的人可能会意外地实现纯虚函数并在其中调用
update()
。这将导致无限数量的函数调用,而这些调用只能在运行时检测到。
如果有人尝试这样做,是否有一些 C++ 习惯用法或关键字会引发编译器错误?
这是一些示例代码。写
Derived
的人没有违反规则,但是写DerivedBad
的人违反了规则。
#include <iostream>
class Base{
private:
virtual void add_to_sum(int incr) = 0;
public:
Base() : m_sum(0), m_other(0) {}
void update(int incr, double other){
this->add_to_sum(incr);
m_other = other;
}
void print_everything() const{
std::cout << "sum: " << m_sum << "\n";
std::cout << "other: " << m_other << "\n";
}
protected:
int m_sum;
private:
double m_other;
};
class Derived : public Base{
virtual void add_to_sum(int incr) override{
this->m_sum += incr;
}
};
class DerivedBad : public Base{
virtual void add_to_sum(int incr) override{
this->m_sum += incr;
this->update(incr, 3.0); // BAD!
}
};
int main() {
// Derived d;
DerivedBad d;
d.update(3, 42);
d.print_everything();
return 0;
}
语言本身无法帮助你——
public
方法是公开的,没有什么可以阻止任何人使用它。
文档很好——你可以把这个问题当作一个陷阱来提及,但用户当然会找到其他搬起石头砸自己脚的方法。
另一种方法是重命名您的
update
方法:通用名称没有说明该方法的作用,因此用户会说“我真的不知道它的作用,但是一个 update
太多比什么都没有”。如果你给它一个更长、更具体的名称,也许从派生类中调用它就没有意义了。
您还可以持有一个专门的成员,上面写着“当前正在更新”,然后您可以在运行时检测到这种情况,然后再进入无限递归。