Как выбрать перегруженную функцию под названием - PullRequest
0 голосов
/ 26 октября 2018

Я новичок в C ++, и я хочу изменить версию функции, которая будет вызываться в этом коде:

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

Как видно из комментария, я хочу, чтобыfunc с аргументом C2 вызывается, когда я разыменовываю указатель, указывающий на класс C2.

Редактировать: просто чтобы уточнить, чего я действительно хочу достичь, следующий код ближе к тому, что я хочу:

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

0 голосов
/ 26 октября 2018

Как уже упоминалось, вы можете сделать func () виртуальной функцией-членом в базе, а затем переопределить ее.Затем вызов YourObject.func () вернет то, что вы хотите.

Виртуальные функции накладываются на поиск vtable, что может в некоторых случаях снизить производительность, но если это известно во время компиляции,введите что-то на самом деле, вы можете использовать CRTP, чтобы сделать «статический полиморфизм».Об этом много статей, и я рекомендую вам сначала изучить шаблоны, если вы пойдете по этому пути, - и определенно понять сначала обычные виртуальные функции.

0 голосов
/ 26 октября 2018
#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;
}
0 голосов
/ 26 октября 2018

Вы можете сначала привести к указателю C2, если знаете, что имеете дело с объектом C2:

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

В качестве альтернативы, вы можете сделать C2 полиморфным, имея виртуальную функцию в C1:

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

И тогда вы можете сделать dynamic_cast:

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

Обратите внимание, что если вы не уверены, какой тип объекта выhave, dynamic_cast вернет нулевой указатель, если он потерпит неудачу, так что вы можете сделать:

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
}

Или, что еще лучше, вообще не использовать указатели, если вы можете избежать этого !!

...