【问题标题】:Instantiation of Base class using Derived classes without using pointers in Object definition使用派生类实例化基类,而不在对象定义中使用指针
【发布时间】:2019-02-05 14:49:08
【问题描述】:

关于this question,我看到所有答案都是使用指向基类的指针(Base *baseObject),然后使用new 关键字来实例化基类的不同实现。

假设有这样的Base 类:

class Base
{
    public:
           int Id;
}

和其他类似的类:

class A : public Base {...}
class B : public Base {...}

是否有条件地实例化基类对象但不使用指针,如下所示:

Base a;
if (...) a = new A();
else if (...) a = new B()

编辑:

基于 cmets 没有强制使用 new 关键字。

【问题讨论】:

  • 使用new 仅对指针有意义,它要求内存来存储类,并且指针将指向该内存。在您的最后一段代码中,Base a; 已经通过这样声明而占用了本地内存,因为a 不是指针
  • 没有强制使用new关键字

标签: c++


【解决方案1】:

您可以使用引用代替指针。

例如:

Derived d;
Base &b = d;

【讨论】:

    【解决方案2】:

    问题是,当使用值而不是指针时,你总是得到相同类型的值。所以对于这种情况:

    Base b;
    

    变量b 只能是b 的一个实例。即使你这样做:

    Derived d;
    Base b = d; // d is sliced into b
    

    变量db 是不同的实例。要进行赋值,编译器必须将d 的值转换为Base 类型的值,就像这样:

    double d = 9.5;
    int i = d; // i is 9, it sliced the .5
    

    所以你必须有某种引用,或者某种允许不同类型的变量。

    使用引用/指针

    这通常是多态性的完成方式。你让b 成为一个引用类型,它可以引用扩展Base 的任何对象实例。

    std::unique_ptr<Base> b = std::make_unique<Derived>();
    

    这会创建一个Derived 类型的唯一指针,并将其分配给Base 类型的唯一指针。 b 现在指向 Derived 对象的实例。

    如果你想使用引用,你必须有一个变量保持足够的时间来使用它,就像这样:

    void foo(Base& refToBase);
    
    void bar() {
        Derived d;
        foo(d);
    } // d is guaranteed to die here.
    

    使用变体

    变体是可以具有多种类型的值的类型。它只能包含一个值,因此它在类型之间“变化”。

    例如:

    std::variant<int, std::string> v;
    
    v = 12;
    v = "text"; 
    

    因此您可以使用它来创建一个变量,该变量可以在派生类型之间变化:

    std::variant<A, B> a_or_b;
    
    if(...) {
        a_or_b = A{};
    } else {
        a_or_b = B{};
    }
    
    std::visit(
        [](Base& b) { /* do stuff with the base */ },
        a_or_b
    );
    

    【讨论】:

      【解决方案3】:

      我不这么认为。

      1. 关键字new 返回一个指向新创建对象的指针。这就是为什么您需要一个基类指针(或特定的指针)来存储它。

      2. 但在您的情况下,更大的问题是Base a;。它已经创建了 Base 类的对象。因此,您尝试将指向派生类中的新对象的指针分配给基类的另一个已存在的对象。

      只需使用指针,一切都很好:

      Base* a;
      if (...) a = new A();
      else if (...) a = new B();
      

      【讨论】:

        【解决方案4】:

        是否有条件地实例化基类对象但不使用指针

        当然:

        if(condition) {
            A a;
        } else {
            B b;
        }
        

        【讨论】:

          猜你喜欢
          • 2021-07-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-01-04
          • 2012-03-14
          • 2016-11-28
          • 2018-10-21
          相关资源
          最近更新 更多