C ++基于组件的架构通过继承实现的良好实践? [英] C++ Is a components-based architeture implemented via inheritance considered good practice?

查看:224
本文介绍了C ++基于组件的架构通过继承实现的良好实践?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我实现一个架构,当我有一个异构对象的容器,可能有或没有一些常见的方法 - 属性。我需要循环遍历他们并应用一些函数,更新一些成员,并通过各种界面调用一些方法。

I'm implementing an architecture when i have a container of heterogeneous objects which may have or not some common methods-attribute. I need to cycle through them and apply some functions, update some members, and call some methods over the various interfaces.

我想到了我相信一个标准架构,基于继承:

I've come up to what i believe a "standard" architecture, based on inheritance:

#include <vector>
#include <memory>
#include <iostream>

using namespace std;

struct Base {
    virtual ~Base() {}
};

struct PositionInterface {
    int x = 0;
    int y = 0;
    virtual ~PositionInterface() {}
};
struct DrawInterface {
    void draw() { cout << "Here i am" << endl; }
    virtual ~DrawInterface() {}
};
struct ChargeInterface {
    int charge = 100;
    virtual ~ChargeInterface() {}
};
struct LifeInterface {
    int life = 100;
    virtual ~LifeInterface() {}
};

struct A: public Base,
          public LifeInterface, public PositionInterface {};
struct B: public Base,
          public DrawInterface, public PositionInterface, public ChargeInterface {};

int main() {
    std::vector<std::shared_ptr<Base>> vec;
    vec.push_back(make_shared<A>());
    vec.push_back(make_shared<B>());

    for (auto & el : vec) {
        auto p = dynamic_cast<PositionInterface *>(el.get());
        if (p) {
            p->x += 10;
            p->y -= 10;
        }
    }
    // ..other stuff
    for (auto & el : vec) {
        auto l = dynamic_cast<LifeInterface *>(el.get());
        if (l) {
            l->life -= 100;
        }
    }
    // ..other stuff
    for (auto & el : vec) {
        auto d = dynamic_cast<DrawInterface *>(el.get());
        if (d) {
            d->draw();
        }
    }
}

看起来像一个基于组件的系统。对我来说,这些接口可能是通过组合添加的组件,而不是继承。这样的东西:

Anyway what I'm looking too looks like a component based system. To me seems like that these interfaces could be components added via composition, not inheritance. Something like this:

struct A: public Base {
    LifeInterface l;
    PositionInterface p;
};

但是我怎么能循环遍历 Base objects dynamic_cast 到正确的界面?

But then how could i cycle through the vector of Base objects dynamic_casting to the right interface?

你看到这种架构的任何缺点除了RTTI和公共变量:-))

Do you see any drawbacks in this kind of architecture (besides RTTI and public variables :-) ) ?

推荐答案


i循环访问基本对象的向量dynamic_casting到正确的接口?

> real 抽象接口,如下:

I'd propose to have real abstract interfaces, like this instead:

struct Base {
    virtual ~Base() {}
};

struct PositionInterface {
    virtual int x() const = 0;
    virtual void x(int value) = 0;
    virtual int y() const = 0;
    virtual void y(int value) = 0;
    virtual ~PositionInterface() {}
};

struct DrawInterface {
    virtual void draw() const = 0;
    virtual ~DrawInterface() {}
};

struct ChargeInterface {
    virtual int charge() const = 0;
    virtual ~ChargeInterface() {}
};

struct LifeInterface {
    virtual int life() const {};
    virtual ~LifeInterface() {}
};






可用作mixins的基本实现类


Base implementation classes that can be used as mixins

class PositionBase : public PositionInterface {
public:
    virtual int x() const { return x_; }
    virtual void x(int value) { x_ = value; }
    virtual int y() const { return y_; }
    virtual void y(int value) { y_ = value; }
    virtual ~PositionBase() {}

protected:
    PositionBase() {}
    int x_;
    int y_;
};

class ChargeBase : public ChargeInterface {
public:
    virtual int charge() const { return charge_; }
    virtual ~ChargeInterface() {}

protected:
    ChargeBase(int charge) : charge_(charge) {}
    const int charge_;
};

class LifeBase : public LifeInterface {
public:
    virtual int life() const { return life_; }
    virtual ~LifeBase() {}

protected:
    LifeBase(int life) : life_(life) {}
    const int life_;
};

并且你的实现如下

struct A 
: public virtual Base
, public LifeBase
, public PositionBase {
    A() : Base(), LifeBase(100), PositionBase() {}
};

struct B 
: public virtual Base
, public DrawInterface
, public PositionBase
, public ChargeBase {
    B() : Base(), PositionBase(), ChargeBase(100)
    virtual void draw() const {
        // Must implement draw()
    }
};




  1. 不要使用公共成员变量,控制这些从继承类。使用如上所示的虚拟getter / setter函数。

  2. 要检查是否支持正确的接口,请使用 dynamic_cast<> 。要对其执行操作,请提供简单的模板函数,例如:

  1. Don't use public member variables, as you can't really control these from inherited classes. Use virtual getter/setter functions as shown above.
  2. To check if the right interface is supported, use dynamic_cast<>. To perform operations on these, provide simple templated functions, like e.g.:







template<class T> void draw(const T& item) {
    DrawInterface* drawableItem = dyn<mic_cast<DrawInterface*>(&item);
    if(drawableItem) {
        drawableItem->draw();
    }
    // Item isn't drawable, ignore or throw exception
}

这篇关于C ++基于组件的架构通过继承实现的良好实践?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆