假设您有两个类A
和B
,其接口事先未知。目标是一般地“结合”' {em} A
和B
在编译时进入名为AB
的新类。
通过组合,我的意思是所有成员函数和所有成员变量以及A
和B
的所有类型都存在于AB
中,具有相同的实现。经典的类继承是不够的;我需要在编译时使用它,因为运行时调度在我的应用程序中是昂贵的。天真的解决方案是创建每个类的实例并转发任何调用;然而,这不是通用的,因为我们假设接口不能提前修复。
使用概念C ++ 11如果有帮助就没问题。如果A
和B
的接口发生冲突,则编译器错误是可以接受的。
这些类实现了基于某些外部数据的实用程序函数,并作为模板参数传递。有几个典型的实用程序经常使用,我想要分解(类A
,B
,C
),但并非所有实例都始终适用(例如,仅{{} 1}}和A
适用,然后我想使用实用程序B
)。代码非常低级,实用程序函数通常在时间关键的循环中被称为非常。
答案 0 :(得分:1)
对于非虚函数,继承不会产生运行时开销。因此,只需不将A
或B
的任何成员声明为virtual
,编译器不会创建任何vtable。
简约的例子是
struct A { void f() { /* ... */ } };
struct B { void g() { /* ... */ } };
struct AB : public A, public B { }; // Provides both f and g.
N.b。,如果A
和B
重叠,编译器会抱怨含糊不清。
(这个答案是基于评论的,并且是为了完整性而给出的;信用是给评论员的。)
答案 1 :(得分:0)
我确信这已经在其他地方得到了解决 - 您正在寻找的是静态继承。实现这一目标的两种模式是基于策略的设计和奇怪的重复模板。小心超载问题。
#include <iostream>
using namespace std;
class A
{
public:
int a;
A() : a(0) {}
int foo_A() { return a; }
};
class B
{
public:
int b;
B() : b(1) {}
int foo_B() { return b; }
};
template<class stinh1, class stinh2>
class AB : public stinh1, public stinh2
{
};
int main()
{
AB<A,B> ab;
cout << ab.foo_A() << endl << ab.foo_B() << endl;
ab.a = 2;
ab.b = 3;
cout << ab.foo_A() << endl << ab.foo_B() << endl;
}
答案 2 :(得分:0)
继承是一种方法(可能是最好的方式)。如果A和B包含具有签名(相同名称和相同参数)的方法,那么您将遇到一个小问题,如果不事先知道API,这很难克服。 您可以尝试静态分析代码,让程序将代码读作文本,解析API并创建两个API组合的新文本,您需要决定如何处理相同的签名问题(您同时调用它们吗?按什么顺序?等等')。这种解决方案更加困难,更容易出错。