Inheritance-free polymorphism
Inheritance-free polymorphism
X:我有一个不相关的容器类对象(向量,映射,树,…)的集合,处理不同不相关类型的对象。这些容器中对象的生命周期在它们的某些子集之间共享。我有一个对象负责它们的同步。我能想到的最简单的同步类实现是有一个BaseContainerLike
指针的向量,其中BaseContainerLike
将是一个为我想要管理的所有容器类对象实现公共接口的类。但并不是所有的都像容器一样。它们可以像容器一样使用,但是让它们从公共基类继承感觉非常奇怪,我担心它会非常强烈地耦合我的设计。
所以我创建了一个ContainerLikeInterface
类,像这样:
struct ContainerLikeInterface {
template<T>
ContainerLikeInterface(T& t)
: create([](int i){ return t->create(i); }), // this is just an example
delete([](int i){ return t->delete(i); }) {}
std::function<void(int)> create;
std::function<void(int)> delete;
};
template<class T>
ContainerLikeInterface make_containerLikeInterface(T& t) {
return ContainerLikeInterface(t);
}
这允许我以一种非侵入性的方式简单地创建一个接口向量(我可以为不同的类型部分专门化构造函数)。使用这种方法的代码比使用继承时稍微快一些,但是它需要更多的内存和更长的编译时间(但我没有优先考虑编译时间)。然而,我不知道这种方法是否可以很好地扩展到我的项目中。我读过一些关于价值语义的文章,其中人们更喜欢将对象所有权转移到接口,所以我有以下问题:
- 这种方法的优缺点是什么? 从长远来看,这会给我带来一些问题吗?
- 我应该使用继承吗?
- 我应该以不同的方式实现这一点吗?
- 我应该用库代替吗?(boost::TypeErasure, adobe::poly,或pyrtsa/poly)
你的基本想法(不需要继承)是好的。我建议使用Adobe。聚。当您每个操作使用1个std::function
时,您有N种虚拟表(指针),加上可能的N个堆分配(取决于是否可以应用SBO(小缓冲区优化))。
您也很可能遇到对象生命周期管理问题。在你的实现中,你假设真正的对象比"接口"存在的时间更长。你迟早会弄错的。这就是我鼓励价值语义方法的原因。Adobe。Poly给你这个
与Adobe。多边形你只得到一个虚表(指针)。它还实现了SBO:可能不是单个分配。
我不一定会使用Boost.TypeErasure。它需要学习另一种"语言"来指定接口,这利用了大量的元编程,到目前为止,它还没有实现SBO。
Adobe。Poly没有很好的文档记录。关于如何使用它的示例,请参阅这篇文章。另外,请参阅这篇文章,了解它是如何实现的。
您的接口与中创建的接口系统略有相似Rust对象系统。经典的基于VMT的接口有一个指向对象的指针,该对象持有指向VMT的指针。你有两个指针:一个指向对象,另一个指向方法表。它(几乎)总是看起来比你已经提到的缺点(内存使用等)的虚拟函数更强大。至于速度,std::function
使用标准分配器来保持指向t
的指针。如果你经常调用ContainerLikeInterface
构造函数,它可能会导致一些性能下降,因为在你的接口中,每个std::function
至少需要一个分配,你可以自己写一个。
您实际上是在创建一个具有ContainerLikeInterface
接口的代理对象,该对象带有指向某些T
的指针或引用。
ContainerLikeInterface
的标准容器。它可能被称为混合设计模式,在c++ 11中使用完美的转发,它看起来像:
#include <vector>
struct IContainerLikeInterface
{
virtual void create(int) = 0;
virtual void erase(int) = 0;
};
template<class T>
struct ContainerLikeInterface : T, IContainerLikeInterface
{
template<class... Args>
ContainerLikeInterface(Args&& ...args)
: T(std::forward<Args>(args)...)
{}
// implement IContainerLikeInterface
void create(int) override;
void erase(int) override;
};
int main() {
ContainerLikeInterface<std::vector<int> > v(10);
v.size();
}
然而,它是侵入性的,因为所讨论的容器的所有声明,如std::vector<int>
,都必须更改为ContainerLikeInterface<std::vector<int> >
。用法保持不变,因为ContainerLikeInterface<T>
是-a T
。
- netcat command in c++
- Difference in displaying cv2 Mat
- C++ MFC Libraries in Travis CI
- 如何在OpenSSL中从configuration.h.in获取configuration.h
- 创建具有 new in 函数和"this is nullptr"异常的对象
- IN, OUT, INOUT Parameters
- 应用程序崩溃并显示"symbol _ZdlPvm, version Qt_5 not defined in file libQt5Core.so.5 with link time reference"
- 有人安装"IITB Simplecpp in mac"吗?
- 从 C 样式字符串中删除子字符串 "in place" 在C++代码中
- 如何修复"error: ‘_1’ was not declared in this scope"?
- Softmax Implementation in C++
- 将 out/in out 参数与 if/switch 的 init 语句一起使用
- IF-nesting in c++
- Gurobi GRBModel and GRBmodel in C++
- Tensorflow Hub in C++
- Centos7 g++ "to_string is not in a member of std"
- InitializeCriticalSectionEx Not Located In KERNEL32.Dll
- 将 lambda 表达式传递给 std::function in C++
- @CPPFLAGS@在 Makefile.in 中意味着什么?
- std::async from std::async in windows xp