在 C++ 中调用辅助类的重写方法

Posted

技术标签:

【中文标题】在 C++ 中调用辅助类的重写方法【英文标题】:Calling overridden method of helper class in C++ 【发布时间】:2020-07-30 08:50:59 【问题描述】:

我来自 Python 背景,目前正在学习 C++ 中的 OOP。

我在弄清楚如何让代码调用继承到 HelperChild 的帮助器类 HelperBase 中的正确方法时遇到问题。

#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;
    
;

我在Base 类中使用的HelperBase 类,它被设置为成员变量。

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 类中覆盖它。我只是想改变帮助类的行为。

【问题讨论】:

HelperBase hb;HelperBase,它不能包含HelperChild 的实例。你需要了解对象切片 【参考方案1】:
    复制构造函数不会复制派生对象,它会获取sliced 并创建一个基础对象。

更详细地说,您可以将复制构造函数视为“按值复制”,派生对象的每个值都将被复制以创建一个基础对象。由于您的 Helper 类没有类成员,因此它没有复制任何内容。

函数也是不可复制的,C++ 通过vtable 处理虚函数。基类会有一个基类的 vtable,这就是为什么 hb.something() 称为基版本。

    最后一行是打印 Helper base,因为您的 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;
;

那么在mainchild.print()会调用属于HelperBase的hb.something()。

要实现多态,您需要一个指针来获取HelperChild 的实例。它被称为依赖注入,我假设您正在尝试实现它。

class Base 
public:
    Base(HelperBase &helperBase) 
        hb = &helperBase;
    

    virtual void print() 
        std::cout << "-- Base" << std::endl;
        hb->something();
    
    HelperBase* hb;
;

【讨论】:

【参考方案2】:

class Base 中的 HelperBase hb 始终是 HelperBase 类型 - 即使您从 Child 类型的实例调用 print。 有多种方法可以实现您想要的。一种选择是使用PIMPL 来存储指向Helper 类的指针。另一种选择是使用CRTP。

【讨论】:

以上是关于在 C++ 中调用辅助类的重写方法的主要内容,如果未能解决你的问题,请参考以下文章

C++ 怎样禁止子类重写父类的某个虚函数?

C++编程中 子类(派生类)能不能重写父类(基类)的函数(方法),除了虚函数?

Java并发辅助类的使用

TrackBar 类的方法

Scala-构造函数

使视觉辅助记录某个类\页面中的所有方法