C++中防止继承陷阱的设计技术
Design Techniques to Defend Against the Pitfalls of Inheritance in C++
摘要
在更改父类中成员函数的签名时,我依靠编译器指向代码中需要更新的每个位置,但编译器未能在子类中指出该函数的重写实例,导致程序出现逻辑错误。我想重新实现这些类,这样在进行此类更改时可以更多地依赖编译器。
通过示例的详细信息
我有以下课程:
class A
{
public:
void foo();
virtual void bar();
}
class B: public A
{
public:
void bar();
}
这就是实现:
void A:foo(){ ... bar(); ... }
void A:bar(){ ... }
void B:bar(){ ... }
注意,当我调用b->foo((时(其中b的类型为b*,b是a的子类(,调用的bar((方法是b:bar((
在更改了A:bar((的类型签名后,比如说A:bar(some_parameter(,我的代码看起来是这样的:
void A:foo(){ ... bar(param); ... }
void A:bar(param) { ... }
void B:bar(){ ... }
现在,当我调用b->foo((时,当然会调用A:bar(param(。我本以为编译器会发现这样的情况,但现在我意识到它做不到。
我将如何实现类A&B以避免此类错误。
我本以为编译器会发现这样的情况,但现在我意识到了
事实上,它可以这样做。你可以在B::bar
的声明中使用override
,如果没有合适的基类函数可以重写,编译器就会出错。
在c++03中检测这个问题的方法是在接口中执行纯虚拟方法,因为它还没有override
说明符(这是因为c++11标准(。如果您更改纯虚拟方法的符号,那么它的所有子类也必须更改它,否则它们将无法编译。
不要依赖于具体的类别。取决于接口。你会做得更好。
你的设计会变成这样:
class IA
{
public:
void foo() { ... bar(); ...}
virtual void bar() = 0;
virtual ~IA() {}
};
class A : public IA
{
public:
void bar() {...}
};
class B : public IA
{
public:
void bar() {...}
};
现在,如果您更改接口中bar的符号,那么它的所有子类也必须更改它。
相关文章:
- 在C++中样板"冷/never_inline"错误处理技术的最佳方法是什么?
- 在 Windows 8/10 技术中完全实时的屏幕捕获,没有延迟
- C++ 关于指针取消引用的技术问题
- 是否有技术原因阻止 Java 中的 final C++ 像 const 一样严格?
- 如何在 SEAL 3.1 中使用 CRT 批处理技术Microsoft?
- 暴力破解技术解决以下问题
- 如何检查 int 变量是否包含合法(非陷阱表示)值?
- std::complex<> in C++ 数学特殊函数:技术规范或提案
- 将一种类型的比特重新解释为不同类型的比特的技术
- 使用聚合初始化模拟默认函数参数是否存在任何陷阱?
- 有什么陷阱用 constexpr string_view 替换全局 const char[]?
- 如何在不同的平台/技术中使用经过训练的神经网络?
- 应用程序未发送所有 SNMP 陷阱
- 在任何地方使用共享指针有哪些陷阱?
- 英特尔C++编译器 19.0 测试版中删除了对英特尔®图形技术的卸载支持
- 使用内联静态数据成员有什么潜在的陷阱吗?
- 如何在两组上做两指针技术
- 反调试器技术:如何使用 VB.NET 对调试器隐藏线程?
- 如何实现没有陷阱的简单请求-响应技术
- C++中防止继承陷阱的设计技术