【问题标题】:How to assign a derived class object to a base class pointer using a function (not the constructor)如何使用函数(而不是构造函数)将派生类对象分配给基类指针
【发布时间】:2020-09-06 13:03:26
【问题描述】:

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

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

class Base
{
    // stuff
};

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

我也有返回Derived 对象的函数。

Derived func(args);

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

Base* ptr = { nullptr };

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

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

到目前为止我做了什么
我知道使用派生类的构造函数是可行的

ptr = new Derived(args);

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

ptr = new Derived;

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

我知道这个,

ptr = new func(args);

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

提前感谢您的任何建议和有用的回复。

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

【问题讨论】:

  • 你能重写func,使它返回Derived*而不是Derived吗?如果是这样,不要忘记制作Base virtual 的析构函数。你也可以写Derived d = func(args); ptr = &Derived;,只是它有点脆弱,因为d 必须比ptr 的任何取消引用都长。
  • 感谢您的及时回复。问题确实是d 不会比指针寿命长,这就是我到目前为止使用new 的原因。
  • func返回一个指针可能是最好的选择,但如果你不能修改func,那么ptr = new Derived(func(args))可能会起作用。
  • @Mestkon 这可能值得作为答案发布。
  • @user157765 复制构造函数或移动构造函数

标签: c++ pointers inheritance derived-class base-class


【解决方案1】:
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();
};

【讨论】:

  • 我可以修改func,所以这可能有效。函数的返回值不是我想的那样,但我会试一试。
【解决方案2】:

func 返回一个指针可能是最好的选择,但如果你不能修改func,那么ptr = new Derived(func(args)) 可能会起作用。这要求Derived 具有复制构造函数或移动构造函数。

【讨论】:

    【解决方案3】:

    您可能想考虑将您的 func 编写为

    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); }

    如果你想将它推广到任何兼容的类和参数类型。您可能还需要 typedef 共享指针以获得更好的可读性。 共享指针也会处理对象的生命周期。

    【讨论】:

      【解决方案4】:

      解决方案总结

      首先,感谢所有回复的人。建议来得非常快,非常有帮助和启发性。

      我不知道这是否违反某些惯例,但由于有多种非常不同的解决方案,我想总结一下。 (如果我更愿意将此作为问题的编辑,请告诉我)。

      所有三个解决方案都应该有效,我现在使用解决方案 2。不过,在了解了有关智能指针的更多信息后,我可能会切换到解决方案 3。

      解决方案 1 - AlexDaniel Langr

      [link to reply]

      更改函数func 使其返回一个指针。

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

      之后,我可以使用该函数直接定义指针ptr

      ptr = func(args);
      

      Alex 还对稍后如何删除ptr 做了一些重要的说明。

      虽然这很有效,但我选择不走这条路,因为我想避免更改 func 的返回值。

      解决方案 2 - Mestkorn

      [link to reply]

      使用复制构造函数。

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

          ptr = new Derived( func(args) );
      

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

      解决方案 3 - DNT

      [link to reply]

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-06-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-22
        • 2016-07-19
        • 2014-04-27
        相关资源
        最近更新 更多