这是我能找到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 ++不支持在运行时更改这样的对象类型,那么实现类似结果的可接受方式是什么?
答案 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的工作方式。