c++ - c++ 类设计、基类继承或外观设计模式
问题描述
我有一个愚蠢的 C++ 设计问题。有没有办法让一个类与多个类中的方法具有相同的方法名称(因此,相同的 API)?
我目前的情况是我有上课的情况
struct A
{
void foo() { std::cout << "A::foo" << std::endl;}
void boo() { std::cout << "A::boo" << std::endl;}
};
struct B
{
void moo() { std::cout << "B::moo" << std::endl;}
void goo() { std::cout << "A::goo" << std::endl;}
};
.... imagine possibly more
我真正想要的是另一个为这些功能充当接口的类。我可能会误解为一个简单接口的外观设计模式,它隐藏了上面实例化类的复杂性,但仍然使用它们相同的接口。
struct C
{
void foo() { ... }
void boo() { ... }
void moo() { ... }
void goo() { ... }
};
对于上面显示的少量方法,通过声明结构 A 和 B 或将它们作为参数传递给结构 C 并在 C 中调用 A 和 B 的方法,这是可行的,但如果 A 有 40 个方法而 B 有 30 个方法,这是不切实际的方法。在 C 中重新声明 70 个具有相同名称的方法来调用 A 和 B 的底层方法,如果我能做得更好的话,似乎是无缘无故的。
我想到了使用基类的第二种解决方案
struct base
{
void foo() { }
void boo() { }
void moo() { }
void goo() { }
};
struct A : public base
{
void foo() { std::cout << "A::foo" << std::endl;}
void boo() { std::cout << "A::boo" << std::endl;}
};
struct B : public base
{
void moo() { std::cout << "B::moo" << std::endl;}
void goo() { std::cout << "A::goo" << std::endl;}
};
尝试使用具有所有函数定义的 shared_ptr。例如
std::shared_ptr<base> l_var;
l_var->foo();
l_var->boo();
l_var->moo();
l_var->goo();
这仍然不能完全满足我的要求,因为一半的方法是在结构 A 中定义的,而另一半是在结构 B 中。
我想知道多重继承是否可以解决问题,但在学校我听说进行多重继承是不好的做法(调试很难?)
有什么想法或建议吗?基本上,管理 struct A 和 B 更容易(等等,因为它是用于抽象目的的自己的类)。但是希望在某种包装器中以某种方式调用他们的方法的灵活性,其中这种复杂性对用户来说是隐藏的。
解决方案
I think that
Redeclaring 70 methods with the same name in C to call the underlying methods of A and B
is the right path.
It is tempting to use multiple inheritance in cases like this to avoid writing pass-through code but I think that is generally a mistake. Prefer composition over inheritance.
I would question whether your user really wants to deal with one interface with 70 methods but if that's really what you want then I don't see why it is "impractical" to write the code in C
:
class C {
A a;
B b;
public:
void foo() { return a.foo(); }
void boo() { return a.boo(); }
void moo() { return b.moo(); }
void goo() { return b.goo(); }
// ...
};
This has the advantage that you can easily change your mind in the future and replace A
and B
with something else without changing the interface of C
.
You can hide the implementation of C
further by using the PIMPL idiom or by splitting C
into an abstract base class C
and an implementation CImpl
.
推荐阅读
- aws-lambda - AWS 抱怨参数类型错误,而实际上并非如此
- laravel - Laravel 多重hasmany 关系限制问题
- python - 如何在python中添加每个月的最后一天
- javascript - JavaScript 模式
- php - 这个简单的 php 代码有什么问题
- node.js - Hyperledger Fabric 客户端 ENDORSEMENT_POLICY_FAILURE
- docker - 在 docker 容器中具有 ignite 缓存的 Spring Boot 应用程序
- excel - 对不同格式的日期列进行排序
- html - 如何根据同一表格行中前一个单元格的值定位链接
- virtualbox - 将 virtualbox vm 暴露给网络