描述从多个接口派生的对象

时间:2015-12-05 21:45:18

标签: c++ inheritance

在C ++中,我有两个纯抽象类(可查看和可移动),可能有很多类型从一个或两个接口派生(Dog,Duck,Cat)。

我想定义一个带有单个参数的函数,其中参数实现两个接口。据我所知,在C ++中,一个对象只能有一个静态类,所以我试着想出不同的方法来解决这个问题。

下面的方法go1有两个Viewable和Movable参数。如果我有类似Dog的类型派生两个接口,我可以调用go1(d, d)。但是,我想阻止go1(d, c) cd是不同的对象(可能有不同的类)。

我可以创建一个从Movable和Viewable派生的新类型MovableAndViwable,但这要求我更改类的定义以从MovableAndViwable派生而不是从两个单独的接口派生。另外,如果我有很多接口并希望将这个想法扩展到两种以上类型,我最终会得到很多“混合”类型(例如,MovableAndViewableAndSavableAndRunnableAndRestorable ......)

所以我的问题是:是否有一个银弹来解决我的问题,正如我所描述的那样。请参阅我的示例代码中的方法go3 - 我想向编译器描述一个对象派生自两个或多个不同且不相关的C ++类。

此外,我对我的课程的其他设计很感兴趣,并且现在想了解除了C ++之外的其他语言如何解决这个问题(假设我不需要使用C ++)。

#include <iostream>

struct Movable { virtual void move() const = 0; };
struct Viewable { virtual void view() const = 0; };
struct MovableAndViewable : Movable, Viewable {};

struct Dog : virtual Movable, virtual Viewable {
    void move() const { std::cout << "Moving\n"; }
    void view() const { std::cout << "Viewing\n"; }
};
struct Duck : virtual Movable, virtual Viewable {
    void move() const { std::cout << "Moving\n"; }
    void view() const { std::cout << "Viewing\n"; }
};
struct Cat : virtual MovableAndViewable {
    void move() const { std::cout << "Moving\n"; }
    void view() const { std::cout << "Viewing\n"; }
};
struct Fish : virtual Movable {
    void move() const { std::cout << "Moving\n"; }
};

void go1(Movable const &m, Viewable const &v) { m.move(); v.view(); }
void go2(MovableAndViewable const &mv) { mv.move(); mv.view(); }
//void go3(Movable and Viewable const &mv) { mv.move(); mv.view(); }

int main()
{
    Dog d;
    Cat c;
    Fish f;

    go1(d, d);
    //go1(f, f); // Nope, Fish isn't Viewable
    //go2(d);
    go1(c, c);
    go2(c);
    //go3(d);
    //go3(c);
    return 0;
}

2 个答案:

答案 0 :(得分:1)

以下方法如何?它似乎符合您传递单个参数的预期目标:

class Movable {
public:
    virtual void move()=0;
};

class Viewable {
public:
    virtual void view()=0;
};

// A stub class, used for parameter passing.

class MovableAndViewable {

public:
    Movable &m;
    Viewable &v;

public:
    template<typename m_and_v> MovableAndViewable(m_and_v &object)
        : m(object), v(object)
    {
    }
};

// Passing only a single parameter:    
void go2(const MovableAndViewable &mv)
{
    mv.m.move();
    mv.v.view();
}

// Example:

class MV : public Movable, public Viewable {

public:

    void move()
    {
    }

    void view()
    {
    }
};

void go3()
{
    MV mv;

    go2(mv);
}

然后,我还要声明:

class const_MovableAndViewable {

public:
    const Movable &m;
    const Viewable &v;

public:
    template<typename m_and_v> const_MovableAndViewable(const m_and_v &object)
        : m(object), v(object)
    {
    }
};

// In order to be able to pass references to const objects:

void const_go2(const const_MovableAndViewable &mv);

答案 1 :(得分:0)

您可以使用dynamic casting。这使您可以访问实例继承的任何类型。

拥有更通用的基类可能很有用,这样在设计函数时就不必在接口之间进行选择(base是常用的类型名称)。