C++ 如何在多个接口上实现多态参数?

C++ 如何在多个接口上实现多态参数?,c++,c++11,interface,polymorphism,code-reuse,C++,C++11,Interface,Polymorphism,Code Reuse,给定一些基本接口A、B、C。。。。N 以及一些实现了一组的假设类: class MyClass1: public A, public B, public N; class MyClass2: public A, public B, public D; 我想创建一个函数,该函数接受一个对象(或指向对象的指针)作为参数指向一个类,该类包括,比如说a和B void myFunc( A&B obj ); 从C++程序员的角度来看,这似乎是荒谬的。从软件架构师的角度来看,这似乎是所有语言都应该

给定一些基本接口A、B、C。。。。N

以及一些实现了一组的假设类:

class MyClass1: public A, public B, public N;
class MyClass2: public A, public B, public D;
我想创建一个函数,该函数接受一个对象(或指向对象的指针)作为参数指向一个类,该类包括,比如说a和B

void myFunc( A&B obj );
从C++程序员的角度来看,这似乎是荒谬的。从软件架构师的角度来看,这似乎是所有语言都应该具备的基本群体

有什么诀窍(模板除外)或解决方案吗

注意:大多数接口不是我提供的,因此(原则上)不可能对接口进行更改

编辑: 这里有一些例子:

class A{
public:
  virtual void draw()=0;
};

class B{
public:
  virtual void edit()=0;
};


class AandB: public A, public B
{
  virtual void draw()override{};
  virtual void edit()override{};
};

//This function know about A, B, but not AandB
void some_function((A+B)& a_and_b) { // That do not work
  a_and_b.draw();
  a_and_b.edit();
}

int main()
{
  AandB c;
  some_function(c); // that is not so easy
}
#包括
使用名称空间std;
A类{};
B类{};

模板我对xaxxon答案投票,
但是如果您想以“虚拟”的方式进行此操作,
您可以执行扩展
A
B
的类

将如下所示:

class A;
class B;
class A_B: public A, public B{
};

class MyClass1: public A_B, public XXX{
};

class MyClass2: public A_B, public YYY{
};

void myFunc( A_B obj );
struct A { void stuff(){ std::cout << "A\n"; } };
struct B { void stuff(){ std::cout << "B\n"; } };
struct C { void stuff(){ std::cout << "C\n"; } };

struct MyType: A, B, C
{
    void stuff() { std::cout << "MyType\n"; }
};

void func(A& a, B& b) // accept both interfaces in func
{
    a.stuff(); // use interface A
    b.stuff(); // use interface B
}

int main()
{
    MyType m;

    func(m, m); // pass both interfaces to func()
}

我同意这看起来很像Java。

您真正需要的是编译器创建一个中间类型(
A
&
B
),其接口同时包含接口
A
和接口
B
)。然后允许实现这两个接口的任何类型绑定到此组合类型的引用

我甚至不知道你如何在语法中引用这种格式塔类型:

void func((A+B)& var); // ???
您可以对当前语法执行类似的操作,而无需编译器在后台创建脚手架,只需接受两次参数,如下所示:

class A;
class B;
class A_B: public A, public B{
};

class MyClass1: public A_B, public XXX{
};

class MyClass2: public A_B, public YYY{
};

void myFunc( A_B obj );
struct A { void stuff(){ std::cout << "A\n"; } };
struct B { void stuff(){ std::cout << "B\n"; } };
struct C { void stuff(){ std::cout << "C\n"; } };

struct MyType: A, B, C
{
    void stuff() { std::cout << "MyType\n"; }
};

void func(A& a, B& b) // accept both interfaces in func
{
    a.stuff(); // use interface A
    b.stuff(); // use interface B
}

int main()
{
    MyType m;

    func(m, m); // pass both interfaces to func()
}

struct A{void stuff(){std::cout减轻模板缺点的一种方法

void myFunc_impl(A& aPart, B& bPart); // aPart and bPart are from the same object.

template <typename T>
void myFunc(T& obj) {
    // static_assert to have better error messages
    static_assert(std::is_base_of<A, T>::value, "T should inherit from A");
    static_assert(std::is_base_of<B, T>::value, "T should inherit from B");
    // Forwarding to implementation
    myFunc_impl(obj, obj);
}
void myFunc_impl(A&aPart,B&bPart);//aPart和bPart来自同一个对象。
模板
无效myFunc(T&obj){
//静态_断言具有更好的错误消息
static_assert(std::is_base_of::value,“T应该从A继承”);
static_assert(std::is_base_of::value,“T应该从B继承”);
//转发至实施
myFunc_impl(obj,obj);
}
1) 强制定义在标题中,难以维护

您只需在标题中添加转发: 代码很短

2) 使用多态指针很难管理

只要您使用引用或指针,这部分就可以使用模板

4) 它使其他一些功能变得困难或不可能,比如虚拟

事实上,模板方法不能是模板,但在这里,您可以转发到虚拟方法

5) 代码很难检查,因为问题只有在使用阶段才明显


您确实必须实例化它才能看到所有错误。

在我看来,
MyClass
继承了
A
B
这两种类型与问题无关。
A
B
是不相关的类型,所以真正的问题是如何编写一个可以接受两种不相关类型中任何一种的函数。@Galik:这就是界面的要点:定义一些行为。A是一个行为(可绘制?),B是另一个行为(可编辑?)。因此,函数接受任何可编辑和可绘制的类。因此,您的问题的答案是:不是A或B,而是A和B。啊,好的。因此,您希望接受任何同时实现
A
B
的类。模板实际上是解决此问题的方法,为什么不需要模板解决方案?我不喜欢模板,因为这是一个非常强大但不安全的特性1)强制定义在标题中,难以维护2)难以使用多态指针进行管理,3)它与语言的其他更好的特性重叠,如多态性、重载函数等。4)它使一些其他特性(如虚拟)变得困难或不可能?5)代码有差异ult需要检查,因为问题只在使用阶段才明显。一般来说:模板用于一般编程,IMO不应被用作代码重用、继承限制和“一切”的小丑.啊,好吧。这很有趣,因为我觉得在继承和术语方面与您的看法基本相反。;o)在这种情况下,A_B应该从A和B继承吗?如果XXX或YYY从A或B继承?感谢您在没有模板的情况下进行的尝试。但实际上,这是不可能的:-要求更改MyClass1和Myclass2-当在中使用超过2个时面对面,它会变得疯狂。如果出现
A_B
A_XXX
B_XXX
等情况,它会有问题。虚拟继承可能会有所帮助。但无论如何都会很混乱。我目前正在尝试将此解决方案应用于我的情况,我将很快接受或进一步评论。你至少需要衰减
T
>is_base_of
也是一个有点可疑的检查。用Detacy更新。你为什么说这是可疑的?我对更细微的TMP细节仍然很陌生。似乎可以工作,但模板正在传播到所有的类层次结构中:-/@AdrianMaire这是什么意思?“通过所有的类层次结构”?相当聪明。复制参数有点令人困惑,但仍然是一个好主意。非常聪明:)那么接受单个参数并传递给func的模板函数呢?例如,类似
template func2(T&a){return func(a,a);}