【发布时间】:2019-04-28 01:17:34
【问题描述】:
从previous question 的回答中得到提示后,我遇到了重载 Scene::addObject 的问题。
重申相关部分并使其自成一体,尽可能减少细节:
- 我有一个继承自
Interface的对象层次结构,其中有Foos 和Bars; - 我有一个拥有这些对象的
Scene; -
Foos 将是unique_ptrs 和Bars 将是shared_ptrs 在我的主要(原因在上一个问题中解释); -
main将它们传递给Scene实例,该实例取得所有权。
最小代码示例是this:
#include <memory>
#include <utility>
class Interface
{
public:
virtual ~Interface() = 0;
};
inline Interface::~Interface() {}
class Foo : public Interface
{
};
class Bar : public Interface
{
};
class Scene
{
public:
void addObject(std::unique_ptr<Interface> obj);
// void addObject(std::shared_ptr<Interface> obj);
};
void Scene::addObject(std::unique_ptr<Interface> obj)
{
}
//void Scene::addObject(std::shared_ptr<Interface> obj)
//{
//}
int main(int argc, char** argv)
{
auto scn = std::make_unique<Scene>();
auto foo = std::make_unique<Foo>();
scn->addObject(std::move(foo));
// auto bar = std::make_shared<Bar>();
// scn->addObject(bar);
}
取消注释被注释的行会导致:
error: call of overloaded 'addObject(std::remove_reference<std::unique_ptr<Foo, std::default_delete<Foo> >&>::type)' is ambiguous
scn->addObject(std::move(foo));
^
main.cpp:27:6: note: candidate: 'void Scene::addObject(std::unique_ptr<Interface>)'
void Scene::addObject(std::unique_ptr<Interface> obj)
^~~~~
main.cpp:31:6: note: candidate: 'void Scene::addObject(std::shared_ptr<Interface>)'
void Scene::addObject(std::shared_ptr<Interface> obj)
^~~~~
取消注释共享和注释独特的东西也可以编译,所以我认为问题在于,正如编译器所说,在重载中。但是我需要重载,因为这两种类型都需要存储在某种集合中,并且它们确实作为指向 base 的指针保存(可能全部移入 shared_ptrs)。
我将按值传递这两个值,因为我想明确说明我拥有Scene 的所有权(并增加shared_ptrs 的引用计数器)。我不太清楚问题出在哪里,我在其他地方找不到任何这样的例子。
【问题讨论】:
-
从
std::unique_ptr<Foo>转换为std::shared_ptr<Scene>与转换为std::unique_ptr<Scene>一样好。 -
很好的 MCVE,很好的问题。我希望看到更多。
-
对我来说,如果类为同一个基类接受两种不同类型的指针,这是一种代码味道。这意味着该类中的内存管理发生了一些不好的事情。所以要修复它,我会删除其中一种方法。可能
unique_ptr版本已过时,因为可以轻松转换为shared_ptr。解决此问题的其他方法是不要使用重载(重命名至少一种方法)应该提高可读性。
标签: c++ c++14 overloading shared-ptr unique-ptr