【问题标题】:Pointer to array of base class, populate with derived class指向基类数组的指针,用派生类填充
【发布时间】:2012-10-14 10:32:23
【问题描述】:

如果我有一个基类,只有虚方法和 2 个派生类 基类,实现了这些虚拟方法。

我该怎么做:

 // causes C2259
 BaseClass* base = new BaseClass[2];

 BaseClass[0] = new FirstDerivedClass;
 BaseClass[1] = new SecondDerivedClass;

或:

// causes "base is being used without being initialized"
BaseClass* base;
// causes CC59 again
BaseClass* base = new BaseClass;

base[0] = FirstDerivedClass();
base[1] = SecondDerivedClass();

(或类似的)

...这样我就可以通过DerivedClass 访问BaseClasss 方法, 但是通过指针和指针是DerivedClasss的数组?

【问题讨论】:

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


    【解决方案1】:

    您的数组类型错误:它存储BaseClass 对象instances 而不是指向它们的指针。由于BaseClass 似乎是抽象的,编译器抱怨它不能默认构造实例来填充你的数组。

    即使 BaseClass 不是抽象的,在 C++ 中多态地使用数组也是 big no-no,所以在任何情况下你都应该做不同的事情。

    通过将代码更改为来解决此问题:

    BaseClass** base = new BaseClass*[2];
    
    base[0] = new FirstDerivedClass;
    base[1] = new SecondDerivedClass;
    

    也就是说,大多数时候最好使用std::vector 而不是普通数组和智能指针(例如std::shared_ptr)而不是哑指针。使用这些工具而不是手动编写代码,将以极低的运行时成本透明地处理大量问题。

    【讨论】:

    • 这个被称为“对象切片”的问题并不特定于数组——它发生在您将派生类按值分配给基类的任何时候。例如。 BaseClass b; b = FirstDerivedClass(); 是可编译的 C++,但仍会静默中断(充其量您可能会收到编译器警告)。
    • 链接似乎被移动了。
    • @Jon You 先生,刚刚拯救了我的一天。我已经声明了一个继承类(带有虚函数)的对象数组,并希望它能够工作。但是,在您的回答中,BaseClass[0] = new FirstDerivedClass; 做了什么?你的意思是base[0] = new FirstDerivedClass;
    • 是的,我还没有尝试过,但似乎应该是 base[0]= 而不是 BaseClass[0] = 。它是对象数组而不是类数组。
    • @user3015682 正确,已修复。不知道为什么我们所有人都花了很多年才发现!
    【解决方案2】:

    这是 C++ 使用 std::vector 而不是简单的数组:

    std::vector<BaseClass*> base;
    base.push_back(new FirstDerivedClass());
    base.push_back(new SecondDerivedClass());
    

    Kerrek SB 注意到最安全的方法是使用std::unique_ptr

    std::vector<std::unique_ptr<BaseClass> > base;
    base.push_back( std_unique_ptr<BaseClass>(new FirstDerivedClass()) );
    base.push_back( std_unique_ptr<BaseClass>(new SecondDerivedClass()) );
    

    【讨论】:

    • 有什么用?速度?可靠性?
    • 怎么样:BaseClass* Base[2];Base[0] = new FirstDerivedClass; Base[1] = 新的 SecondDerivedClass;
    • 使用向量是个好主意,但这不是当前代码的问题。
    • 更好的是std::vector&lt;std::unique_ptr&lt;BaseClass&gt;&gt;
    • 这里的关键点是通过使用 pointers to BaseClass 而不是 BaseClass 对象来避免对象切片。请强调这一点。
    【解决方案3】:

    如果你的 BaseClass 包含纯虚方法,这将无法编译:

    BaseClass* base = new BaseClass[2];
    

    如果没有,你会得到内存泄漏。

    在 c++ 中,这是通过使用带有某种智能指针的 std::vector 或 std::array 来完成的。例如:

    std::vector< std::shared_ptr< BaseClass > > arr( 2 );
    arr[0].reset( new FirstDerivedClass() );
    arr[1].reset( new SecondDerivedClass() );
    

    【讨论】:

    • OP 代码的一个更重要的问题是对象切片,它会默默地破坏程序。
    • @j_random_hacker 这就是为什么我建议使用某种智能指针。存储基类型的对象(如果它没有纯函数)会导致切片
    【解决方案4】:

    这就是答案(来自 Rubby)

    BaseClass* Base[2];
    
    Base[0] = new FirstDerivedClass;
    Base[1] = new SecondDerivedClass;
    

    【讨论】:

    • 这与您的原始代码试图做的事情非常不同。这个数组是在堆栈上分配的,而最初它是在堆上的。
    • 是的,我猜。现在数组是一个指针,数组中有指针。
    【解决方案5】:

    定义一个指针数组,指针类型为BaseClass。 并将派生类的指针分配给数组的元素。 就像:

    BaseClass* base [2];
    base[0] = new FirstDerivedClass;
    base[1] = new SecondDerivedClass;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-06-16
      • 2022-01-03
      • 1970-01-01
      • 1970-01-01
      • 2017-07-18
      • 2016-02-19
      • 2016-12-31
      相关资源
      最近更新 更多