Funkcja o tej samej nazwie, ale inna sygnatura w klasie pochodnej

Mam funkcję o tej samej nazwie, ale z innym podpisem w klasach bazowych i pochodnych. Kiedy próbuję użyć funkcji klasy bazowej w innej klasie, która dziedziczy z pochodnej, otrzymuję błąd. Zob. następujący kod:

class A
{
    public:
    void foo(string s){};
};

class B : public A
{
    public:
    int foo(int i){};
};

class C : public B
{
    public:
    void bar()
    {
        string s;
        foo(s);
    }
};

Otrzymuję następujący błąd z kompilatora gcc:

In member function `void C::bar()': no matching function for call to `C::foo(std::string&)' candidates are: int B::foo(int)

Jeśli usunę {[2] } z klasy B lub zmienię jej nazwę z foo1, Wszystko działa dobrze.

W czym problem?
Author: YSC, 2009-01-04

2 answers

Funkcje w klasach pochodnych, które nie nadpisują funkcji w klasach bazowych, ale które mają tę samą nazwę, będą ukrywać inne funkcje o tej samej nazwie w klasie bazowej.

Ogólnie uważa się za złą praktykę posiadanie funkcji w klasach pochodnych, które mają taką samą nazwę jak funkcje w klasie bas, które nie są przeznaczone do nadpisywania funkcji klasy bazowej, ponieważ to, co widzisz, nie jest zwykle pożądanym zachowaniem. Zwykle lepiej jest podać różne funkcje różne nazwy.

Jeśli chcesz wywołać funkcję bazową, musisz wykonać scope wywołania używając A::foo(s). Zauważ, że spowoduje to również wyłączenie dowolnego mechanizmu funkcji wirtualnych dla A::foo(string) w tym samym czasie.

 66
Author: CB Bailey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-04 15:22:45

To dlatego, że name lookup zatrzymuje się, jeśli znajdzie nazwę w jednej z Twoich baz. To nie będzie wyglądać poza w innych bazach. Funkcja w B cienie Funkcja W A. musisz ponownie zadeklarować funkcję A w zakresie B, aby obie funkcje były widoczne z wewnątrz B i C:

class A
{
    public:
    void foo(string s){};
};

class B : public A
{
    public:
    int foo(int i){};
    using A::foo;
};

class C : public B
{
    public:
    void bar()
    {
        string s;
        foo(s);
    }
};

Edit: prawdziwy opis jaki podaje Standard to (od 10.2/2):

Następujące kroki definiują wynik wyszukiwania nazw w zakresie klasy, C. Po pierwsze, każda deklaracja dla nazwa w klasie i w każdym z jej podrzędnych obiektów klasy bazowej jest brana pod uwagę. A member name f in one sub- obiekt B ukrywa nazwę Członka f W pod-obiekcie a, jeśli A jest pod-obiektem klasy bazowej B. dowolne deklaracje które są tak ukryte są eliminowane z rozważania. Każda z tych deklaracji, która została wprowadzona przez using-declaration jest uważane za każdy Pod-obiekt C, który jest typu zawierającego deklarę- tion wyznaczony przez using-declaration.96) jeżeli powstały zbiór deklaracje nie są wszystkie z obiektów podrzędnych tego samego typu, lub zbiór ma element niestatyczny i zawiera elementy z różnych obiektów podrzędnych, jest dwuznaczność i program jest źle uformowany. W przeciwnym razie ten zestaw jest wynikiem wyszukiwania.

Ma do powiedzenia w innym miejscu (tuż nad nim):

Dla id-wyrażenia [czegoś w rodzaju " foo " ], name lookup zaczyna się w klasie tego zakresu; dla qualified-id [czegoś w rodzaju "A:: foo", A to nested-name-specifier ], name lookup rozpoczyna się w zakresie nested-name-specifier. Wyszukiwanie nazw odbywa się przed kontrolą dostępu(3.4, klauzula 11).

([...] postawione przeze mnie). Oznacza to, że nawet jeśli twój foo w B jest prywatny, foo w A nadal nie zostanie znaleziony (ponieważ Kontrola dostępu dzieje się później).

 93
Author: Johannes Schaub - litb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-04 15:24:04