我有代码:
class A{ //base class
public:
virtual std::string getString(){return "class A";}
};
class B: public A{
public:
std::string getString() {return "it is B class";}
};
class C{
public:
C(){
B b;
a = b;
}
std::string test() {return a.getString();}
private:
A a;
};
int main()
{
C c;
std::cout << c.test();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
c.test()说"A类",但我如何从B类调用方法getString()而不是A?
谢谢!
问题是,在分配给对象时,B
对象会被切片A
.这是因为您按值分配,而不是通过引用或指针分配.既然你a
这样说了
A a;
Run Code Online (Sandbox Code Playgroud)
在赋值期间发生的事情a = b
是将实际状态b
复制到a
.但是,由于a
是一个值对象,只复制A
了对象的一部分b
,并且它的"B-ness"完全丢失了!
为了避免这种情况,你需要a
像其他人所建议的那样声明为指针类型(引用也可以工作,但是你需要大量重写你的例子,因为你不能分配引用,只能初始化它们).如果a
是一个指针(A*
),分配a = b
使a
点所代表的对象b
,这仍然是一个B
对象,所以你会看到你所期望的多态行为.但是,在这种情况下,您必须确保b
即使在退出构造函数后仍保持活动状态 - 否则您会在取消引用时留下一个悬空引用,该引用会导致未定义的行为(读取:您不希望发生的不良事件).
由于@Nawaz已经显示了一个指针示例,我将使用引用给另一个:
class C{
public:
C() : a(b) { // references must be initialized in the constructor initializer list
}
std::string test() {return a.getString();}
private:
B b; // moved to class scope to ensure that it stays alive
A& a;
};
Run Code Online (Sandbox Code Playgroud)
你需要像这样实现:
class C{
public:
C(){
a = new B;
}
std::string test() {return a->getString();}
private:
A *a;
};
Run Code Online (Sandbox Code Playgroud)
这将从getString()
B级调用,而不是A.
你想要做的是被称为"动态多态",它是通过类型基类(即)的指针(或引用)实现的A
,但指针指向派生类类型的对象(即B
).
归档时间: |
|
查看次数: |
525 次 |
最近记录: |