Metody o takiej samej nazwie przy dziedziczeniu

0
#include <iostream>

using namespace std;

struct Base {
    void fun(int i){}
};

struct Derived : Base {
    void fun(){}
};

int main() {
    Base base;
    Derived derived;
    
    base.fun(10);
    derived.fun();
    
    //tego nie chce przepuścić
    derived.fun(20);
    
    return 0;
}

Mam kod jak powyżej i nie mogę zrozumieć, dlaczego kompilator nie chce przepuścić derived.fun(20). Przecież fun(int) i fun() mają inne sygnatury i powinny chyba być traktowane jako zupełnie inne funkcje i wtedy derived.fun(20) po prostu odwoływałby się do void fun(int i) z klasy bazowej, skoro nie jest ona zdefiniowana w pochodnej? Jeżeli w klasie pochodnej nie mam zdefiniowanej fun(), to właśnie tak robi. Byłbym wdzięczny za wyjaśnienia.

2

Overload resolution to nadmiernie skomplikowana sprawa w C++. Kompilator patrzy, czy znajduje nazwę w danej klasie. Jeśli tak - to wyżej już nie patrzy, tylko bierze przeładowania obecne w danej klasie i spośród nich stara się dobrać to właściwe. Tutaj przynajmniej dostałeś błąd, w poniższym przypadku po prostu wejdzie w złe:

struct foo
{
    void x(double){ cout << "double\n"; }
};

struct bar : foo
{
    void x(int){ cout << "int\n"; }
};

// ...

bar b{};
b.x(4.2);

Powyższy zdradliwy przykład wyświetli int.

Możesz wywołać metodę z danej klasy bezpośrednio:

b.foo::x(4.2);

albo dodać funkcje z klasy wyżej do overload setu:

struct baz : foo
{
    using foo::x;
    void x(int){ cout << "baz::int\n"; }
};
0

Dlaczego nie po prostu virtual?

0
Bartosz36 napisał(a):

Dlaczego nie po prostu virtual?

A co tutaj zmieni virtual? :) Błąd wtedy jest dokładnie taki sam, przecież to nie jest przeciążanie tylko przesłanianie.

0

Jest jeszcze taka sztuczka:

struct Derived : Base {
    using Base::fun;
    
    void fun(){}
};

https://wandbox.org/permlink/P6eicx3iPrCil4Vm
IMO jest to najbardziej praktyczne rozwiązanie.

0

Dzięki za wyjaśnienia, macie wirtualna łapkę w górę :) A myślałby człowiek, że przy całym polimorfizmie jaki jest w C++ to będzie działało bez kombinacji - wiadomo czy są jakieś plany co do "uproszczenia" takiego przypadku w c++20 lub dalej?

0

NIE. C++20 ma wprowadzić inne funkcjonalności, które są dużo bardziej zakręcone i trochę usprawnień do nowych featurów od C++11 wzwyż.
A ten przypadek, bardziej ma chronić przed dziwnymi błędami niż jest uciążliwy (pewnie jest to dobrze opisane u Mayers-a, czemu to tak wygląda).

1 użytkowników online, w tym zalogowanych: 0, gości: 1