2012-10-24 121 views
9

如果我有一个基类,其中只有虚拟方法和来自 的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访问BaseClass小号方法, 但通过指针和指针是一个数组DerivedClass s?

回答

8

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

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

修复此由代码改变为:

BaseClass** base = new BaseClass*[2]; 

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

尽管如此,大多数情况下它是优选使用std::vector而不是纯阵列和智能指针(如std::shared_ptr)代替哑指针。使用这些工具而不是手动编写代码将以极低的运行时间成本透明地处理大量问题。如果没有的话,你会得到内存泄漏

BaseClass* base = new BaseClass[2]; 

+1

这个被称为“对象分片”的问题并不特定于数组 - 它随时都会通过值*将派生类分配给基类*。例如。 'BaseClass b; b = FirstDerivedClass();'是可编译的C++,但仍然默默地破解(最好你可能会得到一个编译器警告)。 –

+0

链接似乎被移动。 – user6003859

+1

@ user6003859我更新了它,感谢您的发现! – Jon

3

这是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())); 
+2

但如果我想要一个数组? – Deukalion

+1

什么?速度?可靠性? –

+0

那么:BaseClass * Base [2]; Base [0] = new FirstDerivedClass; Base [1] = new SecondDerivedClass; – Al2O3

2

如果您的BaseClass包含纯虚方法,这将编译失败。

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

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

OP代码的一个更重要的问题是* object slicing *,它会以无声方式破坏程序。 –

+0

@j_random_hacker这就是为什么我建议使用某种智能指针。存储基本类型的对象(如果它没有纯函数)会导致切片 –

0

这是答案(从几度夕阳红)

BaseClass* Base[2]; 

Base[0] = new FirstDerivedClass; 
Base[1] = new SecondDerivedClass; 
+1

这与您的原始代码尝试做的事情*有很* *不同。这个数组在堆栈上分配,而最初它在堆上。 – Jon

+0

是的,我猜。现在该数组是一个指针,数组中有指针。 – Deukalion

0

定义一个指针数组,该指针类型是BaseClass的。 然后将派生类的指针指定给数组的元素。 就像:

BaseClass* base [2]; 
base[0] = new FirstDerivedClass; 
base[1] = new SecondDerivedClass; 
相关问题