【问题标题】:Is it possible to use a method from one parent class to implement an abstract method from another parent class?是否可以使用一个父类的方法来实现另一个父类的抽象方法?
【发布时间】:2021-08-08 12:47:36
【问题描述】:

我有以下课程:

class ServoPart {
private:
    bool move() {
        /* move implementation for a singular servo */
    }
}

struct RoboPart {
    virtual void doJob() =0;
    virtual bool move() =0;
}

class Claw : public ServoPart, RoboPart {
private:
    void doJob() {/* implementation */}
}

class Arm : RoboPart {
private:
    ServoPart major, minor;

    void doJob() {/* implementation */}
    bool move() {/* implementation for two servos */}
}

现在,Arm 可以工作,因为它同时实现了 doJob 和 move。 Claw 但是不起作用,因为它将是一个抽象类,因为它没有实现移动(即使它有来自基类的 move)。当我将bool move() override; 添加到Claw 时,我从链接器中获得对“vtable for Claw”的未定义引用。

有可能以某种方式做到这一点吗?还是我需要将 ServoPart#move 重命名为 ServoPart#moveStep 并从 Claw 中的函数 move 调用它?

【问题讨论】:

  • 为什么class ServoPart 不继承自struct RoboPart? call that from a function move in Claw? 您在搜索class Claw ... { bool move() { return ServoPart::move(); } }? private: bool move() 你不想要protected: 吗?
  • @KamilCuk 因为不是每个ServoPart 都是RoboPart。例如,Arm 类有两个ServoParts,它们不是RoboParts。我会将其添加到 OP 中。根据您的编辑,我猜想在Claw::move() 中调用ServoPart::move() 是没有办法的?

标签: c++ oop overriding abstract-class multiple-inheritance


【解决方案1】:

我试着摆弄一下以了解using 语句是否有用,但似乎它并没有达到你想要的效果。

一种可能的解决方案是使用中间类并手动调用所需的实现,如下所示:

#include <iostream>

class ServoPart {
public:
    virtual bool move() {
        std::cout << "servopart::move" << std::endl;
        return true;
    }
};

struct RoboPart {
    virtual void doJob() =0;
    virtual bool move() =0;
};


struct ServoRoboPart: public ServoPart, RoboPart
{
    virtual bool move(){ ServoPart::move(); return true; };
};

class Claw : public ServoRoboPart {
public:
    void doJob() {std::cout << "claw::doJob" << std::endl;}
};

class Arm : RoboPart {
public:
    void doJob() {std::cout << "arm::doJob" << std::endl;}
    bool move() {std::cout << "arm::move" << std::endl; return true;}
};

int main()
{
    Claw c;
    Arm a;
    a.move();
    a.doJob();
    c.move();
    c.doJob();
}

要使其工作,ServoRoboPart 必须能够看到 ServoPart::move,因此它必须至少为 protected。其他可见性更改是允许它在 ideone 上运行:https://ideone.com/ar5OQl

输出是

arm::move
arm::doJob
servopart::move
claw::doJob

如预期的那样。

【讨论】:

  • 谢谢!老实说,我不太明白为什么/如何工作。我理论上可以将ServoPart::move 设为虚拟并省略中间类吗?还有,为什么是using ServoPart:move 而不是using ServoRoboPart::move?
  • 这是一个错误,那行是不必要的。不,我尝试使move virtual 不允许Claw 编译,如果您想避免在Claw 中再次实现该方法,则需要中间类。我用正确的代码更新了答案。
【解决方案2】:

这里的主要问题是你所有的方法都是私有的,所以它们都不能从定义类之外调用,甚至不能从子类调用。

假设 阻塞 private: 声明可以被移除,那么使用超类中的方法来实现另一个超类中的方法是没有问题的只要它是可访问的,但实现必须是明确的:

class ServoPart {
protected:
    bool move() {
        /* move implementation for a singular servo */
    }
};

class Claw : public ServoPart, RoboPart {
private:
    void doJob() {/* implementation */}
    bool move() {
        return ServoPart::move();
    }
};

}

【讨论】:

    【解决方案3】:

    创建另一个基类“Part”然后从它继承 ServoPart 和 RoboPart 怎么样

    struct Part {
        virtual bool move() = 0;
    };
    
    class ServoPart : public Part{
    private:
        bool move() {
            /* move implementation for a singular servo */
        }
    };
    
    struct RoboPart : public Part{
        virtual void doJob() = 0;
    };
    
    class Claw : public ServoPart, RoboPart {
    private:
        void doJob() {/* implementation */}
        bool move() {/* implementation */}
    };
    
    class Arm : RoboPart {
    private:
        ServoPart major, minor;
    
        void doJob() {/* implementation */}
    
        bool move() {/* implementation for two servos */}
    };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-08-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多