c++是一种基于组件的体系结构,通过继承实现,被认为是良好的实践
C++ Is a components-based architeture implemented via inheritance considered good practice?
我正在实现一个架构,当我有一个异构对象的容器,可能有或没有一些共同的方法属性。我需要循环遍历它们,应用一些函数,更新一些成员,并在不同的接口上调用一些方法。
我认为这是一个基于继承的"标准"架构:
#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();
}
}
}
无论如何,我所看到的看起来也像一个基于组件的系统。在我看来,这些接口可能是通过组合而不是继承添加的组件。像这样:
struct A: public Base {
LifeInterface l;
PositionInterface p;
};
但是,我如何通过Base
对象的向量dynamic_cast
循环到正确的接口呢?
您认为这种体系结构有什么缺点吗(除了RTTI和公共变量:-))?
我建议使用真实的抽象接口,像这样:"但是,我如何循环通过基本对象的向量dynamic_casting到正确的接口?"
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的基实现类
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()
}
};
- 不要使用公共成员变量,因为你不能从继承的类中控制这些变量。如上所示使用虚拟getter/setter函数。
- 使用
dynamic_cast<>
查看是否支持正确的接口。要对这些文件执行操作,可以提供简单的模板化函数,例如:
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
}
RTTI的主要缺点是使用它,所以使它不可能是一件好事。
使用可能为空的指针、接口指针返回函数或类似boost::optional
的类型。
的例子:
class Base
{
public:
virtual LifeInterface* life() { return 0; }
virtual PositionInterface* position() { return 0; }
};
class A: public Base {
public:
LifeInterface* life() { return &l; }
private:
LifeInterface l;
};
// ...
for (auto & el : vec) {
auto l = el.life();
if (l) {
l->life -= 100;
}
}
相关文章:
- 我应该避免多重实现继承吗
- 尝试使用继承和模板实现CRTP.Visual Studio正在生成编译器错误
- 类继承,ENUM 与 AST 类实现的问题
- C++ 使用接口和默认实现继承
- C++ 多重继承:使用基类 A 的实现实现基类 B 的抽象方法
- 将实现从继承的 CRTP 注入到继承的接口类
- 接口实现和私有继承之间的交互
- C 如何仅实现多个继承类的一个构造函数
- 如何在部分类模板专业化中实现继承
- 从接口和实现C 继承
- 编译器如何实现继承
- 为什么无法使用'using'指令实现继承的纯虚拟方法?
- 在子类中实现继承类的方法(param=指向父级的指针)(param=指向子级的指针)
- 从抽象基类的多个分部实现继承
- C++通过继承函数实现继承的抽象函数
- 如何在C++实现继承并解决错误"parent class is not accessible base of child class"?
- 编译器如何实现C++继承
- 代理dll:方法覆盖/方法转发(COM实现继承)
- 类型a必须实现继承的纯虚拟方法b
- 如何实现继承表单fstream的类