在C ++中,我有两个纯抽象类(可查看和可移动),可能有很多类型从一个或两个接口派生(Dog,Duck,Cat)。
我想定义一个带有单个参数的函数,其中参数实现两个接口。据我所知,在C ++中,一个对象只能有一个静态类,所以我试着想出不同的方法来解决这个问题。
下面的方法go1
有两个Viewable和Movable参数。如果我有类似Dog
的类型派生两个接口,我可以调用go1(d, d)
。但是,我想阻止go1(d, c)
c
和d
是不同的对象(可能有不同的类)。
我可以创建一个从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;
}
答案 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
是常用的类型名称)。