在C ++中切换派生类

时间:2013-04-10 16:39:20

标签: c++ inheritance

这是我能找到possible duplication最接近的东西。但是,答案仍然给我留下了问题。

以下是代码示例:

class A {
   A() {}
   virtual void print() = 0;
}

class B : public A {
   B() {}
   void print() { printf("B"); }
}

class C : public A {
   C() {}
   void print() { printf("C"); }
}

int main() {
   A** n;

   n = new A*[4];
   n[0] = new B;
   n[1] = new C;
   n[2] = new B;
   n[3] = new C;

   for(int i = 0; i < 4; i++)
      n[i]->print();
   printf("\n");

   delete n[0];
   delete n[1];
   delete n[2];
   delete n[3];
   delete [] n;
}

使用这段代码,你得到了BCBC&#34;。有没有办法在不分配新对象的情况下更改派生类类型 ?类似的东西:

n[2] = (C*)n[2];

因此,当您打印阵列时,您现在可以获得BCCC&#34;。我在链接的帖子中读到必须这样做是设计不佳的证据。如果是这样的话,可以解释一下吗?对我来说,这似乎是面向对象设计的正常和常见用例。假设所有属性都在基类中定义。类中唯一的区别在于方法的实现。

如果C ++不支持在运行时更改这样的对象类型,那么实现类似结果的可接受方式是什么?

4 个答案:

答案 0 :(得分:1)

最近的事情是在B和C构造函数中实现,它们接受A(或A *)作为输入并将任何数据需要复制到新对象中。然后你应该得到这样的东西。

A* temp = n[2];  
n[2] = new C(A);  
delete temp;  

但更好的解决方案是创建将保存数据的类,并指向实现不同数据操作方式的类的A *。

答案 1 :(得分:0)

指针n[2]指向的对象是B对象。它不能神奇地变成C对象。如果你想要一个C对象,你将不得不创建一个。但是,请不要忘记delete现有的B对象。

delete n[2];
n[2] = new C;

答案 2 :(得分:0)

我不相信你可以从B级转到C级。这两个类都是A类,因为B是A而C是A但是B不是C而C不是B.要么被投入A,但由于切片问题,这是一种危险的做法。在这种情况下,派生类中的数据不会通过强制转换丢失,因此您不会丢失任何内容。但是,您不需要将B或C转换为A以调用父类方法。

或许可以编写一个函数,它将一个B对象作为输入并返回一个C对象和一个带有C对象并返回一个B对象的函数,但你必须自己手动转换所有的工作一个到另一个。

答案 3 :(得分:0)

一旦创建了对象,就不能真正更改对象的类型。但这并不意味着您无法在运行时更改行为。你需要做的是重构你的代码。

class A;

class ImplA
{
public:
  void print (A&) = 0;
};

class A
{
  std::unique_ptr<ImplA> impl;

public:
  A (ImplA* ia) : impl(ia)
  {}

  void print()
  {
    impl->print(*this);
  }

  void changeImpl (ImplA* ia)
  {
    impl.reset(ia);
  }
};

这当然是使用C ++ 11的智能指针,但无论如何都是一样的。您应用软件工程的基本定理:抽象出变化的东西。

我建议您阅读设计模式。它会为你提供想法来做你想要的事情而不会破坏OOP的工作方式。