Kolizja funkcji przy dziedziczeniu

0

Właśnie przerabiam jeden program z C# do C++ i zauważyłem bardzo dziwną rzecz, Działam w Qt Creator 4.11.0, a gcc mam w wersji 9.4.0 na Ubuntu Linux.

W pliku *.pro dopisałem CONFIG += c++20, żeby można było korzystać między innymi z unique_ptr.

Są dwie klasy, klasa foo i klasa bar dziedzicząca po foo. Obie klasy zawierając funkcje Func, ale z różnymi parametrami, a więc te funkcje w ogóle nie kolidują się.

W takim razie, obiekt klasy bar powinien mieć funkcję Func w dwóch wersjach, przy czym wersja bezargumentowa jest odziedziczona z klasy foo.

class foo
{
public:
    void Func()
    {

    }
};

class bar : public foo
{
public:
    void Func(int I)
    {

    }

    void Test()
    {
        Func(); // <--- W tym miejscu kompilator wskazuje błąd
    }
};

Taki kod nie kompiluje się, pojawia się błąd: main.cpp błąd: no matching function for call to ‘bar::Func()’

Czyli kompilator GCC nie widzi funkcji odziedziczonej z klasy bazowej. Natomiast sam Qt Creator, poprzez śledzenie definiecji (klawisz F2) dociera do funkcji bazowej, czyli widzi funkcję, kod jest poprawny.

Natomiast, jak się usunie funkcję Func(int I) z klasy bar, to kod kompiluje się, a ta funkcja nie ma nic wspólnego z tym problemem, nie jest nigdzie użyta.

Jak się z klasy foo skopiuje funkcję Func() do klasy bar, to kod już się kompiluje, ale nie po to wymyślono dziedziczenie, żeby powtarzać te same metody.

Co jest tego przyczyną? Jak to jest, że funkcja o tej samej nazwie, ale innych parametrach przeszkadza w skompilowaniu kodu, skoro nie ma żadnej kolizji z powodu innych parametrów?

Jak spowodować, żeby załączony kod kompilował się bez zmieniania nazwy funkcji? Nie ma tu polimorfizmu, bo nie ma dwóch funkcji o tej samej nazwie i tych samych parametrach.

1

W c++ tylko nazwa ma znaczenie, parametry są ignorowane, więc Func z bara przykrywa func z Foo.

1

Upewnij się, którą chcesz wywołać i użyj ::
np foo::Func();

2

spróbuj

class foo
{
public:
    void Func()
    {

    }
};

class bar : public foo
{
public:
    using foo::Func; // powinno pomóc i powinny być przeciążenia odpowiednio rozpatrzone
    void Func(int I)
    {

    }

    void Test()
    {
        Func(); // <--- W tym miejscu kompilator wskazuje błąd
    }
};

btw:
nie masz jakiejś świeższej wersji z wyższym kompilatorem?

W pliku *.pro dopisałem CONFIG += c++20, żeby można było korzystać między innymi z unique_ptr.

Ło kurła chopie. Jak nie używasz qt(a nawet jak używasz) powinienes użyć cmake a nie plików pro.

0
4Mateusz napisał(a):

Upewnij się, którą chcesz wywołać i użyj ::
np foo::Func();

Właściwie, to nie mam żadnego wyboru. Chodzi o to, żeby obiekt bar miał do dyspozycji funkcję Func() odziedziczony z bar i Func(int I) ze swojej klasy.

revcorey napisał(a):

spróbuj

Zadziałało, problem uważam za rozwiązany.

revcorey napisał(a):

nie masz jakiejś świeższej wersji z wyższym kompilatorem?

W pliku *.pro dopisałem CONFIG += c++20, żeby można było korzystać między innymi z unique_ptr.

Ło kurła chopie. Jak nie używasz qt(a nawet jak używasz) powinienes użyć cmake a nie plików pro.

Na tą chwilę nie mam, ale faktycznie, jestem kilka wersji do tyłu i powinienem zrobić aktualizację.

1

gcc mam w wersji 9.4.0

Patrząc, że GCC jest obecnie w wersji 13.x to problem leży pewnie tutaj, bo powyższy kod działa - https://godbolt.org/z/6feqsT81d

0

Działa, bo jest dodana wstawka using która tą przypadłość eliminuje ;) jak wkleisz oryginalny kod OPa to nie kompiluje się na żadnej wersji. Przyczyna została już wyżej napisana - name hiding.

1
hauleth napisał(a):

gcc mam w wersji 9.4.0

Patrząc, że GCC jest obecnie w wersji 13.x to problem leży pewnie tutaj, bo powyższy kod działa - https://godbolt.org/z/6feqsT81d

Ten kod, czyli po dopisaniu using foo::Func;, u mnie również kompiluje się i działa, więc problemu już nie mam, bo właśnie wiem, co trzeba zrobić w takim przypadku.

Patrząc w drugą stronę, czyli po usunięciu dopisku, czyniąc kod taki sam, jak w pierwszym poście, w GodBold również nie kompiluje się, jest identycznie, jak u mnie. W Godbold działa także po wybraniu GCC 4.6.4 jako kompilatora.

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