防范C ++继承陷阱的设计技巧

时间:2015-08-11 18:53:18

标签: c++ oop inheritance refactoring

摘要

我依靠编译器指向我的代码中的每个位置,我需要在更改父类中的成员函数的签名时进行更新,但编译器未能指出该子函数的重写实例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,以避免这类错误。

2 个答案:

答案 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() {...}
};

现在,如果您更改界面中栏的符号,其所有子类也必须更改它。