摘要
我依靠编译器指向我的代码中的每个位置,我需要在更改父类中的成员函数的签名时进行更新,但编译器未能指出该子函数的重写实例class,在我的程序中导致逻辑错误。我想重新实现这些类,以便在进行此类更改时可以更多地依赖编译器。
通过示例详细说明
我有以下课程:
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,以避免这类错误。
答案 0 :(得分:1)
我预计这样的情况会被编译器捕获,但我现在意识到了 它不能这样做。
实际上,它可以这样做。您可以在override
的声明中使用B::bar
,如果没有合适的基类函数,编译器将会出错。
答案 1 :(得分:-1)
在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() {...}
};
现在,如果您更改界面中栏的符号,其所有子类也必须更改它。