如何为 c++ 赋予属性类(接口)
我构建了几个类(A
、B
、C
...),它们在同一个 BaseClass
上执行操作。示例:
struct BaseClass {
int method1();
int method2();
int method3();
}
struct A { int methodA(BaseClass& bc) { return bc.method1(); } }
struct B { int methodB(BaseClass& bc) { return bc.method2()+bc.method1(); } }
struct C { int methodC(BaseClass& bc) { return bc.method3()+bc.method2(); } }
但正如您所看到的,每个类 A
、B
、C
... 仅使用 的可用方法的子集code>BaseClass
并且我想将 BaseClass
分成几个块,以便清楚它使用了什么和没有使用什么。例如,解决方案可能是使用多重继承:
// A uses only method1()
struct InterfaceA { virtual int method1() = 0; }
struct A { int methodA(InterfaceA&); }
// B uses method1() and method2()
struct InterfaceB { virtual int method1() = 0; virtual int method2() = 0; }
struct B { int methodB(InterfaceB&); }
// C uses method2() and method3()
struct InterfaceC { virtual int method2() = 0; virtual int method3() = 0; }
struct C { int methodC(InterfaceC&); }
问题是每次添加新类型的操作时,我都需要更改 BaseClass
的实现。例如:
// D uses method1() and method3()
struct InterfaceD { virtual int method1() = 0; virtual int method3() = 0; }
struct D { int methodD(InterfaceD&); }
struct BaseClass : public InterfaceA, public InterfaceB, public InterfaceC
// here I need to modify the existing code to add class D
{ ... }
你知道我可以做到这一点的干净方法吗?
感谢您的帮助
编辑:
我忘了提及它也可以使用模板来完成。但我也不喜欢这个解决方案,因为所需的接口没有明确出现在代码中。您必须尝试编译代码以验证所有必需的方法是否已正确实现。另外,它需要实例化不同版本的类(每个 BaseClass 类型模板参数一个),而这并不总是可能或不需要的。
I have built several classes (A
, B
, C
...) which perform operations on the same BaseClass
. Example:
struct BaseClass {
int method1();
int method2();
int method3();
}
struct A { int methodA(BaseClass& bc) { return bc.method1(); } }
struct B { int methodB(BaseClass& bc) { return bc.method2()+bc.method1(); } }
struct C { int methodC(BaseClass& bc) { return bc.method3()+bc.method2(); } }
But as you can see, each class A
, B
, C
... only uses a subset of the available methods of the BaseClass
and I'd like to split the BaseClass
into several chunks such that it is clear what it used and what is not. For example a solution could be to use multiple inheritance:
// A uses only method1()
struct InterfaceA { virtual int method1() = 0; }
struct A { int methodA(InterfaceA&); }
// B uses method1() and method2()
struct InterfaceB { virtual int method1() = 0; virtual int method2() = 0; }
struct B { int methodB(InterfaceB&); }
// C uses method2() and method3()
struct InterfaceC { virtual int method2() = 0; virtual int method3() = 0; }
struct C { int methodC(InterfaceC&); }
The problem is that each time I add a new type of operation, I need to change the implementation of BaseClass
. For example:
// D uses method1() and method3()
struct InterfaceD { virtual int method1() = 0; virtual int method3() = 0; }
struct D { int methodD(InterfaceD&); }
struct BaseClass : public InterfaceA, public InterfaceB, public InterfaceC
// here I need to modify the existing code to add class D
{ ... }
Do you know a clean way I can do this?
Thanks for your help
edit:
I forgot to mention that it can also be done with templates. But I don't like this solution either because the required interface does not appear explicitly in the code. You have to try to compile the code to verify that all required methods are implemented correctly. Plus, it would require to instantiate different versions of the classes (one for each BaseClass type template parameter) and this is not always possible nor desired.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
使用模式 适配器
use pattern Adapter
我认为不使用其基类的某些元素的派生类没有任何问题。
派生类不需要也不应该使用其可用的一切。
因此,我认为您的原始实现没有任何问题,并且无需重构它。
I see nothing wrong with a derived class that does not use some elements of its base class.
A derived class is not, and should not be, required to use everything available to it.
Hence, I see nothing wrong with your original implementation, and no need to refactor it.
methodA、methodB... 的调用者是否应该知道实际使用了方法 1、2、3 中的哪一个?
如果这样做,您可以将 BaseClass 拆分为 3 个不同的接口,并准确添加方法 1、2 和 3 所需的接口参数,如下所示:
调用者仍然可以选择从多个接口继承,如下所示:
Should the callers of methodA, methodB, ... know which of the methods 1,2,3 are actually used?
If they do, you could split up the BaseClass in 3 different interfaces, and add exactly the interface arguments needed by the methods 1, 2 and 3, like this:
The caller can still choose to inherit from multiple interfaces, like this: