C++ - 通过单个指针访问多个对象的接口

Luk*_*ens 5 c++ oop polymorphism templates interface

我需要存储一个指向对象的指针的容器。这些对象有一些我想要强制执行(可能在编译时)和使用的通用方法/属性(接口)。例子:

struct A{
    void fly(){}
};

struct B{
    void fly(){}
};

A a;
B b;
std::vector<some *> objects;
objects.push_back(&a);
objects.push_back(&b);

for(auto & el: objects)
    el->fly();
Run Code Online (Sandbox Code Playgroud)

更简单的解决办法是AB继承公共基类一样FlyingClass

struct FlyingClass{
    void fly(){}
};
struct A: public FlyingClass { ...
struct B: public FlyingClass { ...
Run Code Online (Sandbox Code Playgroud)

并创建一个

std::vector<FlyingClass *> objects;
Run Code Online (Sandbox Code Playgroud)

这将起作用并强制执行我只能添加到objects可以飞行的东西(实现FlyingClass)的事实。

但是如果我需要实现一些其他常见的方法/属性而不将它们与上述基类耦合呢?

例子:

struct A{
    void fly(){}
    void swim(){}
};

struct B{
    void fly(){}
    void swim(){}
};
Run Code Online (Sandbox Code Playgroud)

我想做:

for(auto & el: objects) {
    el->fly();
    ...
    el->swim();
    ...
}
Run Code Online (Sandbox Code Playgroud)

更一般地说,我将能够调用传递这些指针之一的函数并访问两个常用方法/属性,例如:

void dostuff(Element * el){
    el->fly();
    el->swim();
}
Run Code Online (Sandbox Code Playgroud)

我可以尝试从另一个接口继承,例如:

struct SwimmingClass{
    void swim(){}
};

struct A: public FlyingClass, public SwimmingClass { ...
struct B: public FlyingClass, public SwimmingClass { ...
Run Code Online (Sandbox Code Playgroud)

但是容器应该包含什么?

std::vector<FlyingClass&&SwimmingClass *> objects;
Run Code Online (Sandbox Code Playgroud)

当然,我可以实现SwimmingFlyingClass,但是如果我需要RunningClass等等怎么办。这将是一场噩梦。换句话说,如何在不耦合它们的情况下实现指向多个接口的指针?

或者有一些重新思考问题的模板方式?如果有一种优雅且可维护的方式来执行此操作,即使运行时类型信息在我的应用程序中也是可以接受的。

Jac*_*ack 0

你所要求的东西一般来说没有意义,这就是为什么没有简单的方法来做到这一点。

您要求能够将异构对象存储在集合中,并且接口甚至不同。

在不知道类型的情况下如何迭代集合?你被限制在最不具体的地方,或者被迫做dynamic_cast指针和交叉手指。

class Entity { }

class SwimmingEntity : public Entity {
  virtual void swim() = 0;
}

class FlyingEntity : public Entity {
  virtual void fly() = 0;
}

class Fish : public SwimmingEntity {
  void swim() override { }
}

class Bird : public FlyingEntity {
  void fly() override { }
}

std:vector<Entity*> entities;
Run Code Online (Sandbox Code Playgroud)

这是合法的,但不会向您提供有关运行时实例功能的任何信息Entity。除非你用rtti(或手动rtti)来解决它们,否则它不会有任何结果,dynamic_cast那么优势在哪里呢?