抽象类型符合标准容器
Abstract types Meet std Containers
我一直在努力解决一个涉及抽象类型及其派生类以及std容器的设计问题。我有一个可行的解决方案,但我想看看是否可以改进。我为"…"道歉。但这是为了让设计问题更清楚。
// the base class
class B {
private:
...
public:
// the virtual function which makes B an abstract type
virtual void func(...) = 0;
...
};
// the 1st derived class
class D1 : public B {
...
void func(...) {...}
};
// the 2nd derived class
class D2 : public B {
...
void func(...) {...}
};
基于这个问题,D1
和D2
都必须指向或包含B
的一些实例,而不知道它们的具体类型。目前,我使用点到的方法,这意味着D1
和D2
包含一些指向B
的指针。
此外,那些指向B
实例的实例实际上是在递归组合中B
的高级实例之间共享的。为了明确起见,我将扩展D1
的定义。
class D1 : public B {
private:
B *d1_b1;
B *d1_b2;
...
public:
D1 (B *b1, B *b2) {...}
B* func(...) {...}
...
};
现在,尽管d1_b1
和d1_b2
由D1
或D2
的一些高级实例共享,但我认为任何高级对象都不应保持较低级别对象的所有权或生存期。相反,我使用了一个带有unique_ptr
s的std容器,例如:
std::vector<std::unique_ptr<B>> unique_b_objs;
unique_b_objs
在首次调用递归构造的作用域中声明,并通过引用传入并递归使用。
现在,每次创建D1
或D2
的新对象时,都会将相应的unique_ptr
推回到unique_b_objs
中。本质上,指向B对象的原始指针用于递归组合,但B对象的生存期和所有权由std容器管理。
我希望到目前为止我已经说清楚了。它正在按预期工作。但我正在尝试去掉原始指针。我能想到两种方法,但现在都不起作用。
- 使用"包含"方法。本质上,所有的
B *
在D1
和D2
中变为B
。但B
是一种抽象类型,这意味着编译器甚至不会编译类似D1 (B b1, B b2) {...}
的东西 - 在容器中使用引用。这可以通过
reference_wrapper
来完成。但是,由于对象是在递归中本地创建的,因此引用在作用域之外将变得无效。这意味着我们不能在递归调用之间传输引用
一种工作方法是使用shared_ptr
。但是没有必要在每个递归步骤共享所有权。这也会导致性能开销。
在这一点上,感谢您通读这个问题。我希望我已经说清楚了。如果你能想出比unique_ptr
s+原始指针的容器更好的方法,请告诉我。
使用非拥有的原始指针是非常好的(例如,请参阅此答案)
如果您的目标是在构造函数和派生类的成员中使用引用而不是指针,那么您可以在不对设计进行重大更改的情况下做到这一点
例如,
#include <iostream>
#include <vector>
#include <memory>
class B {
private:
public:
virtual void func() = 0;
};
std::vector<std::unique_ptr<B>> arena;
class D1 : public B {
B &b1;
B &b2;
public:
D1(B &b1, B &b2) : b1(b1), b2(b2) { }
void func() {
std::cout << "D1n";
b1.func();
b2.func();
}
};
class D2 : public B {
B &b;
public:
D2(B &b) : b(b) { }
void func() {
std::cout << "D2n";
b.func();
}
};
class D3 : public B {
public:
D3() { }
void func() {
std::cout << "D3n";
}
};
int main() {
auto node = std::make_unique<D3>(); // make new object
auto& nodeRef = *node; // get reference to the object
arena.push_back(std::move(node)); // transfer ownership to the vector,
// nodeRef is not invalidated
auto node1 = std::make_unique<D2>(nodeRef); // use reference
auto& node1Ref = *node1;
arena.push_back(std::move(node1));
auto node2 = std::make_unique<D3>();
auto& node2Ref = *node2;
arena.push_back(std::move(node2));
auto node3 = std::make_unique<D1>(node1Ref, node2Ref);
arena.push_back(std::move(node2));
node3->func();
}
相关文章:
- 无法创建抽象类的实例
- 用pybind11包装C++抽象类时出错
- 如何处理从一个对象传递到另一个在C++中具有公共抽象类的对象的消息
- 有没有办法按值将纯抽象类的所有子类传递给 C++ 中的函数?
- 抽象类错误,请参阅声明" "是抽象的
- 将自定义函数传递到基抽象类中以延迟执行
- 将包含抽象类和普通类C++包导出到 Python
- C++:处理抽象类中的错误时出现问题
- C ++如何在原始抽象类中创建一个函数,该函数接受派生类的输入
- 在 C++ 中使用另一个头文件中的抽象类
- ATL::CComContainedObject<contained>: C2259 无法实例化抽象类
- C++:从抽象类重写纯虚拟运算符重载
- 如何创建shared_ptr抽象类的容器
- .h 或.cpp文件中的抽象类或两者兼而有之?
- 从抽象类继承以创建另一个抽象类时,我应该重新声明所有虚函数吗?
- E0322:不允许使用抽象类类型 " " 的对象
- 可视抽象类 c++(错误 LNK 2001:未解析的外部符号)
- 提升 - 类没有名为"序列化"的成员(抽象类)?
- 如何将子类作为函数的参数传递给期望基类,然后将该对象传递到指向这些抽象类对象的指针向量中?
- 对纯抽象类中方法的未定义引用