减少父子类代码重复

Reducing parent-child class code duplication

本文关键字:代码 子类 父子      更新时间:2023-10-16

我在多态性和父子关系方面遇到了问题。以下面的两个类为例,想象一下我在应用程序中创建了一个"child"对象。在对象之外,我调用的唯一函数是update(),它反过来调用对象中我需要的所有其他函数。此调用序列中唯一在"parent"answers"child"上不同的函数是dosomething2()。

class parent 
{
    public:
        void dosomething1() {}; //amongst other things, calls dosomething2
        void dosomething2() {};
        void update() {}; //amongst other things, calls dosomething1
}
class child : public parent
{
    void dosomething2() {}
}

我意识到,如果我创建一个"child"对象并调用update(),那么只会调用父类函数。我不得不将update()和dosomething1()复制到子类中,然后一切都按预期进行。这不是一个很好的解决方案,因为有很多重复的代码——有办法改进吗?

更新:由于提供了答案,我用虚拟dosomething2()函数更新了父类。现在调用了正确的函数,我不必将dosomething1()复制到子类中。不幸的是,如果我不将update()复制到子类,我会得到一个符号查找错误(父类和子类都在一个库中)。

class parent 
{
    public:
        void dosomething1() {}; //amongst other things, calls dosomething2
        virtual void dosomething2() {};
        void update() {}; //amongst other things, calls dosomething1
}
class child : public parent
{
    void dosomething2() {}
    /*void update() {}; //symbol lookup error if this is left uncommented */
}

更新2符号查找错误与代码无关。我做了一个make clean,然后make(它构建了一个.so库和可执行文件),现在一切都按预期进行。

您没有将基类中的函数标记为virtual:

class parent 
{
    public:
        virtual void dosomething1() {}; //amongst other things, calls dosomething2
        virtual void dosomething2() {};
        void update() {}; //amongst other things, calls dosomething1
}

此外,仅供参考,您正在做的被称为模板方法模式

如果需要dynamic-polymorphism,则应在父类中使用关键字virtual。然后在子类中重新实现或不重新实现虚拟函数。

class parent 
{
    public:
        void dosomething1() {}; //amongst other things, calls dosomething2
        virtual void dosomething2() {};
        void update() {}; //amongst other things, calls dosomething1
}

您应该将相关函数设置为virtual。假设您希望从对update()的调用中调用childdoSomething1()doSomething2()

class parent 
{
    public:
        virtual void dosomething1() {}; //amongst other things, calls dosomething2
        virtual void dosomething2() {};
        void update() {}; //amongst other things, calls dosomething1
}
class child : public parent
{
    virtual void dosomething2() {}
}

然后,对childupdate()的调用将调用派生类的方法(如果可用)。请注意,update() is not virtual, so you should have no filed called会更新in子级,否则将隐藏该名称。