关于c ++:即使通过引用传递,也会调用基类方法而不是派生方法

Base class method being called instead of derived, even when passed by reference

本问题已经有最佳答案,请猛点这里访问。

我有3个班:ABAnotherClass。其中B来源于A

1
2
3
4
5
class A {
public:
    A(){}
    virtual void method() {//default action}
};

然后我有一个派生类,B:

1
2
3
4
5
class B : public A {
public:
    B(){}
    void method() {//redefine action}
};

AnotherClass

1
2
3
4
5
6
7
class AnotherClass {
public:
    AnotherClass(A& a);
    A a;
    anotherMethod(){ a.method()}
};
AnotherClass :: AnotherClass(A& a) : a(a) //initialization

因此,如果我用B的对象构造AnotherClass的对象:

1
2
B b();
AnotherClass myObj(b);

请记住,由于B继承了AAnotherClass接受了A的对象,所以我可以成功地将B对象作为论据。

我称之为:

1
myObj.anotherMethod();

我希望它执行anotherMethod(),当它执行时,我希望它调用属于B的重新定义的method(),而不是调用A中定义的默认method()

我想我的问题是因为我把AnotherClass的论点指定为class A的对象。但是,我不想把这个论点改为class B的一个对象,因为我还有CDE类,它们也直接从A继承。所以我想使用基类作为参数类型,这样我不仅能够传递B对象。但是,我在这个网站上看到了一些老的帖子,大多数建议的解决方案是通过引用来传递派生对象(B,我正在这样做。

有人能解释为什么会这样吗?


构造函数的参数可以。它是通过引用A子对象传递的B类型的对象。问题是,只将A子对象(而不是派生对象)复制到成员变量A中。然后,当调用a.method()时,那里只有一个基对象,因此调用基函数。

解决方案是使成员变量成为参数的指针或引用(而不是副本)。(请注意,无论哪种情况,您都需要确保传递的对象至少与AnotherClass对象一样长。


您正在将构造函数切片到AnotherClass。注意,作为成员,您有一个类型为A的值。所以编译器正在做正确的事情。在你称之为a.method()的时候,你没有B


只有当它是指针A* a时,它才能工作。查找多态性。http://www.cplusplus.com/doc/tutorial/多态性/

如果你不想了解更多,请阅读这篇文章