如果派生类具有私有变量,派生类的数组就不起作用

我有一个抽象基类和2个不同的类,它们实现了基类中的虚函数。如果派生类具有私有变量,派生类的数组就不起作用

我把这些放在一个数组中,而对于“derived1”类来说,这是可行的。 但是,如果我创建一个具有一些额外私有变量的“derived2”类的数组,代码将在运行时进行编译,但会发生错误。

#include <iostream> 

class base{

protected:

int inner_a;

int inner_b;

public:

void setInner(int a,int b){inner_a=a;inner_b=b;};

virtual int doStuff()=0;

};

class derived1: public base{

public:

virtual int doStuff();

};

class derived2: public base{

private:

int tmpVar;//works if I remove

public:

int doStuff();

};

int derived2::doStuff(){

return inner_a-inner_b;

}

int derived1::doStuff(){

return inner_a+inner_b;

}

int main(){

base *classAry1 = new derived1[3];//this works

base *classAry2 = new derived2[2];//derived2 has extra private variables

classAry1[0].setInner(1,3);

classAry1[1].setInner(10,7);

std::cout <<classAry1[0].doStuff() <<std::endl;;

std::cout <<classAry1[1].doStuff() <<std::endl;

classAry2[0].setInner(1,3);

classAry2[1].setInner(10,7);

std::cout <<classAry2[0].doStuff() <<std::endl;;

std::cout <<classAry2[1].doStuff() <<std::endl;

return 0;

}

任何人都可以帮助我,关于如何把派生类放在一个std数组?

感谢

编辑:

的代码段错误,并Valgrind的告诉我

-2

==25096== Use of uninitialised value of size 8 

==25096== at 0x400AC9: main (abc.cpp:52)

==25096==

==25096== Invalid read of size 8

==25096== at 0x400AC9: main (abc.cpp:52)

==25096== Address 0x0 is not stack'd, malloc'd or (recently) free'd

==25096==

==25096==

==25096== Process terminating with default action of signal 11 (SIGSEGV)

==25096== Access not within mapped region at address 0x0

==25096== at 0x400AC9: main (abc.cpp:52)

回答:

一种阵列derived1对象(或derived2对象)的不能被解释为阵列base对象。数组不是多态的。只有独立对象可以是多态的,即derived1base具有IS-A关系。但array of derived1array of base没有IS-A关系。您的阵列(既不classAry1也不classAry2)都不能真正“工作”。

换句话说,这

base *classAry1 = new derived1[3]; 

base *classAry2 = new derived2[2];

已经没有任何意义,即使它的正式结构良好的代码。

第一个阵列“似乎正常工作”,只是纯粹的意外。您的代码行为未定义,即使您使用classAry1

如果您想要一个存储多态实体的数组(或容器),则必须将指针存储到该数组中的实际对象,而不是存储实际对象本身。

在您的具体情况下,代码可以通过以下方式重写。 (它看起来并不很漂亮,我只是做它来说明的原则,因为不知道你的意图完全是很难选择最好的方法)

int main(){ 

derived1 *d1s = new derived1[2];

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

classAry1[0] = &d1s[0];

classAry1[1] = &d1s[1];

derived2 *d2s = new derived2[2];

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

classAry2[0] = &d2s[0];

classAry2[1] = &d2s[1];

classAry1[0]->setInner(1,3);

classAry1[1]->setInner(10,7);

std::cout << classAry1[0]->doStuff() << std::endl;;

std::cout << classAry1[1]->doStuff() << std::endl;

classAry2[0]->setInner(1,3);

classAry2[1]->setInner(10,7);

std::cout << classAry2[0]->doStuff() << std::endl;;

std::cout << classAry2[1]->doStuff() << std::endl;

delete[] classAry2;

delete[] d2s;

delete[] classAry1;

delete[] d1s;

return 0;

}

回答:

一般来说,你不能做你正在尝试做的。您正在调用未定义的行为。当一个系统面临未定义的行为时,它可以自由地执行任何想要的操作(包括擦除硬盘驱动器),并且仍然符合标准。问题是你的代码。

回答:

尝试使用std :: vector < base *>而不是原始数组。

回答:

你不能做到这一点。一个类型为T1的数组不能转换为另一个类型为T2的数组,即使其中一个是从另一个类型派生的。

您的线路上

base *classAry1 = new derived1[3];//this works 

你确实有什么是数组的第一元素的基类指针,只有。其他元素是“迷失”。使用基类指针访问除第一个之外的数组成员是未定义的行为。

回答:

classAry2 [1] => & classAry2 + sizeof(base),它不等于实际派生的2的大小 ,它是> sizeof(base)或derived1。 您需要到达classAry2的正确地址(第二个元素),即 classAry2 + sizeof(derived2)。

最简单的解决方法是使用指向base *的指针数组访问它们。 使用基准** =分配基准数组* 然后为每个元素分配正确的实例(派生或派生2或基准) 这样当您使用classAry [n]或classAry ++时,它将始终指向正确的地址。

回答:

阅读:http://www.parashift.com/c++-faq/proper-inheritance.html

非常好,描述和它给你留下的启示:)感

以上是 如果派生类具有私有变量,派生类的数组就不起作用 的全部内容, 来源链接: utcz.com/qa/263607.html

回到顶部