0

我有一个简单的程序问题分配派生类阵列新

$ cat a.cpp 
#include <iostream> 
class MyClass { 
    public: 
     virtual void check() { 
      std::cout << "Inside MyClass\n"; 
     } 
}; 

class MyClass2: public MyClass { 
    public: 
     int* a; 
     virtual void check() { 
      std::cout << "Inside MyClass2\n"; 
     } 
}; 

int main() { 
    MyClass *w, *v; 
    w = new MyClass2[2]; 
    v = new MyClass2; 
    std::cout << "Calling w[0].check\n"; w[0].check(); 
    std::cout << "Calling v->check\n"; v->check(); 
    std::cout << "Calling w[1].check\n"; w[1].check(); 
} 
$ g++ a.cpp 
$ ./a.out 
Calling w[0].check 
Inside MyClass2 
Calling v->check 
Inside MyClass2 
Calling w[1].check 
Segmentation fault 

我认为这是可以使用新分配的派生类对象。另外,v-> check()似乎工作正常。

回答

5
w = new MyClass2[2]; 

这创建了两个MyClass2对象的数组。它是类型MyClass2[2]。新表达式返回一个指向此数组的初始元素的指针,并将该指针指定给w

w[1].check(); 

这对待w作为指针以MyClass对象的数组,MyClass2对象的数组。

您不能将派生类对象的数组视为它是基类对象的数组。如果你希望能够使用派生类对象,你需要一个指针数组:

MyClass** w = new MyClass*[2]; 
w[0] = new MyClass2; 
w[1] = new MyClass2; 
+0

((MyClass2 *)&w [1]) - > check()也给出了分段错误。 – highBandWidth

+0

当然,这是正确的。为了获得所需的行为,'w'需要是指向基类的指针或引用的数组。 –

+3

我想你的意思是'MyClass ** w = new MyClass * [2];'。对? – Nawaz

1

由于詹姆斯似乎消失了,我想我应该张贴正确的解决方案:

MyClass** w = new MyClass*[2]; //Note the difference from James solution! 
w[0] = new MyClass2; 
w[1] = new MyClass2; 

std::cout << "Calling w[0].check\n"; w[0].check(); 
std::cout << "Calling w[1].check\n"; w[1].check(); 

这应该工作!

+0

我饿了,然后离开午餐。 –

+0

@詹姆斯:我知道你在某个地方很忙。所以认为要纠正这个错字。希望你不介意。 :-) – Nawaz

2

作为@James McNellis和@Nawaz提出的解决方案(这是正确的)的扩展,您可以通过使用您可用的容器类和智能指针来避免大量混淆。即std::vectorstd::array(取决于您的编译器版本,这可能位于tr1命名空间中,或者您可能需要下载boost库以使用它)和shared_ptr(但也有其他人可以选择)。

+0

良好的通话。就目前而言,此代码的所有版本都会泄漏内存。智能指针将有助于避免这种情况。 –