gpt4 book ai didi

c++ - 如何仅通过对基类的引用来复制派生类

转载 作者:行者123 更新时间:2023-12-02 01:26:29 24 4
gpt4 key购买 nike

我试图存储对从外部类的 std::set 内的嵌套抽象基类继承的对象的引用。

让我先向您展示代码,因为我认为这样更清楚:

Class.h接口(interface):

#ifndef Class_H_
#define Class_H_

#include <set>
#include <memory>

class Class
{
public:
class AbstractBase;
private:
std::set< std::shared_ptr<AbstractBase>> set;
public:
Class();
~Class();

void add(AbstractBase& object);
};

#endif

Abstract.h接口(interface):

#ifndef ABSTRACT_H_
#define ABSTRACT_H_

#include "Class.h"

class Class::AbstractBase
{
friend class Class;

public:
virtual ~AbstractBase();
private:
virtual void foo(int in) = 0;
};

#endif

Derived.h接口(interface):

#ifndef DERIVED_H_
#define DERIVED_H_

#include "Class.h"
#include "AbstractBase.h"

class Derived : private Class::AbstractBase
{
public:
~Derived() override;
private:
void foo(int in) override;
};

#endif

add.cc 实现:

#include "Class.h"
#include "AbstractBase.h"

void Class::add(AbstractBase& object)
{
// create a shared pointer to object
// and insert it in the set
set.insert(std::make_shared<AbstractBase>(object)); // <-- this is where it fails
}

因此,我将有多个不同的派生对象,全部继承自 AbstractBase,它们需要一起存储在 std::set 容器中。由于纯虚函数,编译失败。起初,我没有使用std::shared_ptr并认为这是失败的原因,我发现this SO 答案建议使用 std::shared_ptr 代替。我仍然在 Class::add 中遇到编译错误,因为 AbstractBase::foo 是纯的,但我认为 std::shared_ptr能解决这个问题吗?

我发现了类似的问题,但没有任何内容可以帮助我解决我的具体问题。有人可以向我解释我做错了什么吗?

谢谢。

编辑:哇!感谢您提供信息丰富的答案,我需要一些时间来彻底理解它们并看看什么最适合我。完成后我会更新这个问题!

最佳答案

您的函数尝试做的是复制一个对象,为该拷贝分配一个共享实例,并存储指向该拷贝的指针。

由于您的意图是在集合中“存储引用”,因此您可能打算将对象存储在其他地方并且实际上并不需要拷贝。如果这些引用的对象是共享的,那么正确的解决方案是传递共享指针:

void Class::add(std::shared_ptr<AbstractBase> ptr)
{
set.insert(std::move(ptr));
}

如果引用的对象不是共享的,则不能使用共享指针引用它们。您可以使用非拥有指针来代替:

std::set<AbstractBase*> set;

void Class::add(AbstractBase* ptr);

但是,使用非拥有方法时要非常小心,以使引用的对象至少在被集合引用的时间内保持事件状态。这一点很重要。引用可以用作 add 的参数,但我建议不要这样做,因为对于调用者来说,函数存储指向参数的指针的时间可能比函数执行的时间长。

<小时/>

如果您确实想要复制,则可以使用返回共享指针的虚函数。示例:

class Class::AbstractBase
{
public:
virtual std::shared_ptr<AbstractBase> copy() = 0;
// ...

class Derived : private Class::AbstractBase
{
public:
std::shared_ptr<AbstractBase> copy() override {
auto ptr = std::make_shared<Derived>(*this);
return {ptr, static_cast<Class::AbstractBase*>(ptr.get())};
}
// ...

void Class::add(AbstractBase& object)
{
set.insert(object.copy());

为了避免在多个派生类型中重复相同的拷贝,您可以使用 CRTP。

关于c++ - 如何仅通过对基类的引用来复制派生类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59630362/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com