如何使用函数(不是构造函数)将派生 class 对象分配给基 class 指针

How to assign a derived class object to a base class pointer using a function (not the constructor)

问题总结
我不知道如何通过函数(不是构造函数)使用新运算符创建派生 class 的对象,并让基 class 指针指向它。

设置
我的项目中有一个抽象基础 class 和一个派生 class:

class Base
{
    // stuff
};

class Derived : public Base
{
    //stuff
    //constructor:
    Derived(args);
};

我还有 returns 一个 Derived 对象的功能。

Derived func(args);

在某些时候,我声明了一个基class指针

Base* ptr = { nullptr };

我希望它稍后指向一个 Derived 对象。

我想要的
我想使用 func 创建一个 Derived 对象,并能够在代码后面通过指针 ptr 访问它。

到目前为止我做了什么
我知道它可以使用派生的 class 的构造函数

ptr = new Derived(args);

或者只是它的默认构造函数,如果它存在的话

ptr = new Derived;

但是,我有充分的理由不能在我的案例中使用构造函数,因为派生对象的配置更加复杂。在这种情况下,我想用函数 func.

创建这个对象

我知道这个,

ptr = new func(args);

不起作用,因为 new 需要一个类型。我怎样才能实现这样的行为?

在此先感谢您的任何建议和有用的回复。

注意: 我正在使用 new 因为我需要访问也在其创建范围之外的 Derived 对象。

Derived * func(args)
{
  Derived *p = new Derived();
  // do your custom stuff:
  p->x = args->i;
  p->y = 3;

  // return the pointer
  return p;
}

// ...

ptr = func(args);

以后别忘了删除ptr。为了能够调用 Derived 的析构函数,稍后使用指向 Base 的指针,您必须将析构函数设为虚拟。

class Base
{
  // ...
  virtual ~Base();
};

Return 来自 func 的指针可能是最佳选择,但如果您无法修改 func,那么 ptr = new Derived(func(args)) 可能会起作用。这要求 Derived 具有复制构造函数或移动构造函数。

您可能想考虑将函数编写为

template<class T, class TA> boost::shared_ptr<T> func(TA args) { return boost::make_shared<T>(args); }

template<class T, class TA> std::shared_ptr<T> func(TA args) { return std::make_shared<T>(args); }

如果您想将其概括为任何兼容的 class 和参数类型。您可能还想对共享指针进行 typedef 以获得更好的可读性。 共享指针还将处理对象生命周期。

解决方案总结

首先感谢所有回复的人。这些建议来得非常快,非常有帮助和指导。

我不知道这是否违反了某些约定,但由于有多种非常不同的解决方案,我想总结一下。 (如果我宁愿把它作为对问题的编辑,请告诉我)。

三种方案都应该有效,我现在使用方案2。但是,我可能会在了解更多有关智能指针的知识后切换到解决方案 3。

解决方案 1 - Alex and Daniel Langr

更改函数 func 使其 return 成为一个指针。

Derived* func(args)
{
    Derived *p = new Derived();
    // do some complicated configuration
    return p;
}

之后我可以直接用函数定义指针ptr.

ptr = func(args);

Alex 还对如何删除 ptr 发表了一些重要评论。

虽然效果很好,但我选择不遵循这条路径,因为我想避免更改 func 的 return 值。

解决方案 2 - Mestkorn

使用复制构造函数。

这可能是最简单的解决方案。通过使用复制构造函数,我可以简单地写

    ptr = new Derived( func(args) );

虽然这需要一个 copy/move 构造函数,但它与我项目中的默认复制构造函数配合得很好。我不需要实施任何新的东西。这是我目前在代码中的解决方案。

解决方案 3 - DNT

使用智能指针,更具体地说是 shared_ptrstd::shared_ptrboost::shared_ptr。)这个概念对我来说是全新的。谢谢!

我将了解更多相关信息并可能会切换到此选项,因为它听起来像是一个 cleaner 解决方案。如果我理解正确的话,相对于其他两种解决方案的优势是我不必考虑内存泄漏或删除指针。
一旦我正确地解决了这个问题,我会回来扩展这个总结。