简体   繁体   中英

Calling overridden method of helper class in C++

I come from a Python background, and currently I'm learning OOP in C++.

I'm having problems figuring out how to get the code to call the correct method in a helper class HelperBase that is inherited to 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;
    }
};

The HelperBase class i used in the class Base , where it is set as a member variable.

class Base {
public:
    Base(HelperBase &helperBase) : hb(helperBase) {}

    virtual void print() {
        std::cout << "-- Base" << std::endl;
        hb.something();
    }
    HelperBase hb;
};

Then this class is used as the base class of the class Child :


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

The main method is

int main() {
    HelperChild helperChild;

    Child child(helperChild);
    child.print();
    return 0;
}

This outputs the following:

HelperChild
-- Base
HelperBase

Why isn't the 'HelperChild' printed in the last line? What changes do I have to do to achieve this? (I'm not sure if I have used virtual in the correct way).

EDIT: In the actual case im trying to figure out, Base::print is a really large method that I don't want to override in the Child class. I just want to change the behaviour of the helper class.

  1. Copy constructor will NOT copy derived object, it will get sliced and create a base object.

To elaborate, you may consider copy constructor as "copy by value", every value of derived object would be copied to create a base object. Since your Helper classes have no class members, it copied nothing.

Also function is not copyable, C++ handles virtual functions by vtable . A base class would have a vtable of base class, that's why hb.something() called the base version.

  1. Last line is printing Helper base because your Base has a HelperBase but not a derived 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;
};

Then in main , child.print() will call the hb.something() which belongs to HelperBase .

To achieve polymorphism, you need a pointer to take the instance of HelperChild . It's called Dependency Injection and I assumed you were trying to achieve it.

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

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

The HelperBase hb in class Base is always of type HelperBase - even if you call print from an instance of type Child . There are various ways to achieve what you want. One option is to use PIMPL to store a pointer to a Helper class. A different option is to use CRTP .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM