How to choose the overloaded function called

Viewed 187

I am a beginner in C++, and I want to change the function version which will be called in this code:

#include <iostream>

class C1 {};

class C2 : public C1 {};

void func(C1 var) {
    std::cout << "Func 1" << std::endl;
}

void func(C2 var) {
    std::cout << "Func 2" << std::endl;
}

int main() {
    C1 *teste1 = new C1;
    C1 *teste2 = new C2;

    func(*teste1);                 // Want "Func 1"
    func(*teste2);                 // Want "Func 2"

    return 0;
}

As it can be seen in the comment, what I want is that the func with an C2 argument be called when I dereference the pointer which points to a C2 class.

Edit: Just to clarify what I really want to achieve, the following code is closer to what I want:

#include <iostream>
#include <list>

class C1 {};

class C2 : public C1 {};

void func(C1 var) {
    std::cout << "Func 1" << std::endl;
}

void func(C2 var) {
    std::cout << "Func 2" << std::endl;
}

int main() {
    std::list<C1*> teste;

    teste.push_back(new C1);
    teste.push_back(new C2);

    // Want to print:
    // Func 1
    // Func 2
    for(auto i: teste) {
        func(*i);

    }

    return 0;
}
3 Answers

You can cast to a C2 pointer first if you know you're dealing with a C2 object:

func(*teste1);                   // Want "Func 1"
func(*static_cast<C2*>(teste2)); // Want "Func 2"

Alternatively, you can make C2 polymorphic by having a virtual function in C1:

class C1 {
public:
    virtual ~C1() {}
};

And then you can do a dynamic_cast:

func(*dynamic_cast<C2*>(teste2)); // Want "Func 2"

Note that if you're not sure which kind of object you have, dynamic_cast will return a null pointer if it fails, so you can do:

if(dynamic_cast<C2*>(teste2)) {
    func(*dynamic_cast<C2*>(teste2)); //If it's a C2, call the C2 overload
} else {
    func(*teste2); //If it's a C1, call the C1 overload
}

Or even better, don't use pointers at all if you can avoid it!!

As mentioned already, you can make func() a virtual member function in the base, and then override it. Then a call to YourObject.func() would return what you want it to.

Virtual functions have the overhead of a vtable lookup, which can kill performance in some cases, but if it is known at compile time which type something actually is, you can use CRTP to do "static polymorphism". There are many articles about this and I recommend you learn templates first if you go this route - and definitely understand regular virtual functions first.

#include <iostream>

class C1 {
public:
    virtual void func(){
        std::cout << "Func 1" << std::endl;
    }
};

class C2 : public C1{
public:
    void func() override{
        std::cout << "Func 2" << std::endl;
    }
};

int main() {
    C1* teste1 = new C1;
    C1* teste2 = new C2;

    teste1->func();                 // Want "Func 1"
    teste2->func();                 // Want "Func 2"

    return 0;
}
Related