【问题标题】:Double inheritance and polymorphism. How to have two separated members from one base class?双继承和多态。如何从一个基类中拥有两个独立的成员?
【发布时间】:2017-12-09 14:57:48
【问题描述】:

我需要对从 BaseA 继承的对象使用 do_something 的多态性,但我的 D 对象应该有两个名为 enabled 的独立成员。我的意思是 D::changeEnabled() 应该改变 SecondBaseB::BaseA::enabled = 0SecondBaseC::BaseA::enabled = 0 并且这两个成员应该是分开的(不同的)。是否可以具有多态性而不使用虚拟继承?没有virtual public BaseA 我有模棱两可的错误。但是对于虚拟继承,我只有一个BaseA::enabled

//
// main.cpp
//
#include <iostream>
#include "D.h";

void do_something(BaseA& o) {
    o.changeEnabled();
}

int main() {
  SecondBaseB b;
  SecondBaseC c;
    D d;
  do_something(b);
  do_something(c);
    do_something(d);
    std::cout « "Hello, World!" « std::endl;
    return 0;
}

//
// BaseA.h
//
class BaseA {
protected:
    bool enabled;
public:
    BaseA();
    virtual void changeEnabled() = 0;
};

//
// BaseA.cpp
//
#include "BaseA.h"

BaseA::BaseA() : enabled(true) {

}

//
// SecondBaseB.h
//
class SecondBaseB : virtual public BaseA{
public:
    virtual void changeEnabled();
};

//
// SecondBaseB.cpp
//
#include "SecondBaseB.h"

void SecondBaseB::changeEnabled() {
    enabled = !enabled;
}

//
// SecondBaseC.h
//
#include "BaseA.h"

class SecondBaseC : virtual public BaseA {
public:
    virtual void changeEnabled();
};

//
// SecondBaseC.cpp
//
#include "SecondBaseC.h"

void SecondBaseC::changeEnabled() {
    enabled = !enabled;
}

//
// D.h
//
#include "SecondBaseB.h"
#include "SecondBaseC.h"

class D : public SecondBaseB, public SecondBaseC{
public:
    virtual void changeEnabled();
};

换个说法。我有以下场景:带有engine 成员的基础抽象类Car。我创建了从 Car 继承的 DieselCarElectricCar。然后我想创建 HybridCar,它将继承自 DieselCarElectricCar 并有两个不同的 engines。使用虚拟继承只有一个引擎。如果不使用virtual,我将无法完成以下操作:

void testDrive(Car* c) {
c->drive();
c->drive();
}

HybridCar h;
ElectricCar e;

testDrive(&h);
testDrive(&e)

【问题讨论】:

  • 模板和std::enable_if() 是处理此类情况的绝佳工具。
  • 如果有两个不同的enabled 成员,你希望do_something(d) 做什么?
  • 使用virtual 基类表示您只需要一个该类型的基对象。既然你想要两个,不要使用虚拟继承。 D 必须明白有两个基础并采取相应的行动。

标签: c++ inheritance polymorphism


【解决方案1】:

谈论您的 Car 场景,要获得关于 Car 子类的多个信息,这些子类不止一个 Engine,可以使用 Composite 重构代码模式,以这种方式:

  • 汽车拥有发动机
  • Engine 是一个接口或抽象类,其作用类似于 组件
  • Leaf 是 Engine 的具体子类,其含义类似于 ElectricEngineDieselEngine 等...李>
  • PowerUnit 的作用类似于 Composite,因此它拥有对某些 Engine 的引用

然后Car的每个具体子类的每个构造函数都初始化属性

Engine* engine;

在抽象类Car中以正确的方式声明。
例如,

 ElectricCar(){
     //other members
     engine=new ElectricEngine();
 }

 DieselCar(){
    //other members
    engine=new DieselCar();
 }

 HybridCar(){
   //hybrid car is composed by an electric and diesel engine
   engine=new PowerUnit(Engine* engines);
 }

如果抽象类看起来像

 class Engine{
    private bool enabled;
    public:
       virtual Engine* getEngine(int number=0){ return this};
       virtual final bool isEnabled(){return this->enabled};
       virtual final void setEnabled(bool value){ this->enabled=value;}
    }

getEngine() 方法必须在子类 PowerUnit 的真实函数中实现。

class PowerUnit{
     private:
        Engine*[] engines;
     public:
       PowerUnit(){
         engines[0]=new ElectricCar();
         engines[1]=new DieselCar();
       }
       getEngine(int number){ return engines[number];}
   }

最后,如果客户 (Car) 想要检查混合动力汽车哪个引擎处于活动状态(或两者都处于活动状态),它可以使用指针 engine,如以下方式检查第一个引擎是否处于活动状态:

engine->getEngines(0)->isEnabled;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-29
    • 2018-06-23
    • 2017-01-26
    • 1970-01-01
    相关资源
    最近更新 更多