使用子类对象初始化的多态基类对象的数组

时间:2011-08-26 10:50:39

标签: c++ visual-studio-2005 initialization polymorphism virtual

对于复杂的标题感到抱歉。我有这样的事情:

class Base
{
public:
  int SomeMember;
  Base() : SomeMember(42) {}
  virtual int Get() { return SomeMember; }
};

class ChildA : public Base
{
public:
  virtual int Get() { return SomeMember*2; }
};

class ChildB : public Base
{
public:
  virtual int Get() { return SomeMember/2; }
};

class ChildC : public Base
{
public:
  virtual int Get() { return SomeMember+2; }
};

Base ar[] = { ChildA(), ChildB(), ChildC() };

for (int i=0; i<sizeof(ar)/sizeof(Base); i++)
{
  Base* ptr = &ar[i];
  printf("El %i: %i\n", i, ptr->Get());
}

哪个输出:

El 0: 42
El 1: 42
El 2: 42

这是正确的行为(在VC ++ 2005中)吗?说实话,我希望这段代码不要编译,但确实如此,但是它没有给我我需要的结果。这有可能吗?

3 个答案:

答案 0 :(得分:8)

是的,这是正确的行为。原因是

Base ar[] = { ChildA(), ChildB(), ChildC() };

通过将三个不同类的对象复制到class Base的对象上并生成class Base的对象来初始化数组元素,因此您可以从数组的每个元素中观察class Base的行为。 / p>

如果要存储不同类的对象,则必须使用new分配它们并存储指针。

答案 1 :(得分:2)

为了实现您期望的多态行为,您应该使用指向Base的指针数组并通过new创建对象:

Base* ar[] = { new ChildA(), new ChildB(), new ChildC() };

答案 2 :(得分:0)

实际发生的是:

  1. 由于ar []的类型是Base,因此将3 * sizeof(Base)内存量分配给ar。

  2. 由于您尚未为Base声明显式复制构造函数,因此调用base的默认复制构造函数,它只是将ChildA,ChildB和ChildC对象的“Base”部分按位复制到数组中包含的Base对象中ar(默认的复制构造函数足够智能,不会将Child对象的虚拟指针按位复制到Base虚拟指针中)。

  3. ar [0],ar [1]和ar [2]的虚拟指针指向Base :: Get,因此调用Base :: Get。

  4. 此处需要注意的是,在执行之前,对象的虚拟指针所指向的函数始终是已知的。

    在这种情况下,运行时事先知道arr由“Base”对象组成,所以它设置了它们的vptr,以便在它们被分配内存时指向Base :: Get。