Nick Mack
Nick Mack

Reputation: 75

Access derived virtual function from base class, good practice?

Is there a good practice to access a derived virtual function from it's base class? Here's what I got so far:

class A {
public:
    enum class AType{A,B,C,D};   
    AType aType = AType::A;    
    virtual void Do(){}
};

class B : public A {
public:  
    int val = 0;  
    B(int i) {
        aType = AType::B;
        val = i;
    }   
    void Do(){
        std::cout << val << std::endl;
    }
};

int main(){
    std::map<std::string, A> bunch;  
    bunch["01"] = B(10);
    bunch["02"] = B(15);
    bunch["03"] = B(80);

    for (auto& [k, b] : bunch){
        switch (b.aType){
        case A::AType::A:
            break;
        case A::AType::B:
            static_cast<B&>(b).Do();
            break;
        }
    }
}

I'm not too happy about using a switch there, any advice would be appreciated!

Upvotes: 0

Views: 110

Answers (2)

John Park
John Park

Reputation: 1764

You should assign a pointer or reference to use polymorphism in C++. If you assign a child class as value, there would be a object slicing. I'd use std::unique_ptr than raw pointer like following, which prints out 10 15 80 as excepted.

#include <memory>
#include <map>

class A {
public:
    enum class AType { A, B, C, D };
    AType aType = AType::A;
    virtual void Do() {}
};

class B : public A {
public:
    int val = 0;
    B(int i) {
        aType = AType::B;
        val = i;
    }
    void Do() override {
        std::cout << val << std::endl;
    }
};

int main() {
    std::map<std::string, std::unique_ptr<A>> bunch;
    bunch["01"] = std::make_unique<B>(10);
    bunch["02"] = std::make_unique<B>(15);
    bunch["03"] = std::make_unique<B>(80);

    for (auto& [k, b] : bunch) {
        b->Do();
    }

    return 0;
}

Upvotes: 2

Bartosz Bosowiec
Bartosz Bosowiec

Reputation: 171

First, what're showing isn't what I'd call "calling from base class". Otherwise, calling derived virtual methods from a base class method is one of the main reasons to use virtual functions. The other reason is to call a method via pointer to base class, like you intend to do.

Also, as mentioned above, in:

bunch["01"] = B(10);

a temporary object of B type is silently cast (sliced) to object of class A. You should use perhaps map of pointers to A.

Upvotes: 1

Related Questions