我来自Python,目前正在学习C++中的OOP。
我在弄清楚如何获取代码以继承到HelperBase的辅助类HelperChild中调用正确的方法时遇到问题。

#include <iostream>

class HelperBase {
public:
    HelperBase() {}

    virtual void something() {
        std::cout << "HelperBase" << std::endl;
    }
};

class HelperChild : public HelperBase {
public:
    HelperChild() {}

    void something() {
        std::cout << "HelperChild" << std::endl;
    }
};

我在HelperBase类中使用的Base类,在其中将其设置为成员变量。
class Base {
public:
    Base(HelperBase &helperBase) : hb(helperBase) {}

    virtual void print() {
        std::cout << "-- Base" << std::endl;
        hb.something();
    }
    HelperBase hb;
};
然后,将该类用作Child类的基类:

class Child : public Base {
public:
    Child(HelperChild &helperChild) : Base(helperChild) {
        helperChild.something();
    }
};

main方法是
int main() {
    HelperChild helperChild;

    Child child(helperChild);
    child.print();
    return 0;
}
输出以下内容:
HelperChild
-- Base
HelperBase
为什么最后一行没有打印“HelperChild”?我必须做些什么改变才能做到这一点? (我不确定我是否以正确的方式使用了virtual)。
编辑:在实际情况中,我试图弄清楚,Base::print是一个非常大的方法,我不想在Child类中覆盖。我只想更改助手类的行为。

最佳答案

  • 复制构造函数将不会复制派生对象,它将获取sliced并创建基础对象。

  • 详细地说,您可以将复制构造函数视为“按值复制”,派生对象的每个值都将被复制以创建基础对象。由于您的Helper类没有任何类成员,因此它不会复制任何内容。
    函数也是不可复制的,C++通过vtable处理虚函数。基类将具有基类的vtable,这就是为什么hb.something()称为基版本的原因。
  • 最后一行正在打印Helper基础,因为您的Base具有HelperBase但没有派生的HelperChild
  • class Base {
    public:
        Base(HelperBase &helperBase) : hb(helperBase) {}  // hp(helperBase) means you still have a helper base.
    
        virtual void print() {
            std::cout << "-- Base" << std::endl;
            hb.something();
        }
        HelperBase hb;
    };
    
    然后在main中,child.print()将调用属于HelperBase的hb.something()。
    为了实现多态,您需要一个指针来获取HelperChild的实例。这称为依赖注入(inject),我以为您正在尝试实现它。
    class Base {
    public:
        Base(HelperBase &helperBase) {
            hb = &helperBase;
        }
    
        virtual void print() {
            std::cout << "-- Base" << std::endl;
            hb->something();
        }
        HelperBase* hb;
    };
    

    10-05 18:12