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 klasy pochodnej, pojawia się błąd. Zobacz poniższy 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ę int foo(int i){};
z zajęć B
lub zmienię jego nazwę z foo1
, wszystko działa dobrze.
Jaki jest z tym problem?
Odpowiedzi:
Funkcje w klasach pochodnych, które nie przesłaniają funkcji w klasach bazowych, ale mają taką samą nazwę, będą ukrywać inne funkcje o tej samej nazwie w klasie bazowej.
Generalnie uważa się, że posiadanie funkcji w klasach pochodnych, które mają taką samą nazwę jak funkcje w klasie basu, a które nie mają zastępować funkcji klasy bazowej, jest złą praktyką, ponieważ to, co widzisz, nie jest zwykle pożądanym zachowaniem. Zwykle lepiej jest nadać różnym funkcjom różne nazwy.
Jeśli chcesz wywołać funkcję podstawową, musisz określić zakres połączenia przy użyciu
A::foo(s)
. Zauważ, że to również wyłączyłoby jakikolwiek mechanizm funkcji wirtualnychA::foo(string)
w tym samym czasie.źródło
Dzieje się tak, ponieważ wyszukiwanie nazw zatrzymuje się, jeśli znajdzie nazwę w jednej z twoich baz. W innych bazach nie będzie wyglądać dalej. Funkcja w B pomocniczym funkcję w A. należy ponownie zadeklarować funkcję w zakresie b, tak, że obie te funkcje są widoczne od 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); } };
Edycja: rzeczywisty opis podany przez standard to (od 10.2 / 2):
W innym miejscu (tuż nad nim) ma do powiedzenia:
([...] podane przeze mnie). Zauważ, że oznacza to, że nawet jeśli twoje foo w B jest prywatne, foo w A nadal nie zostanie znalezione (ponieważ kontrola dostępu ma miejsce później).
źródło
void A::foo(class basic_string<char,char_traits<char>,allocator<char> >)' in
klasy B „ponieważ metody lokalnej` int B :: foo (int)”z tej samej nazwie. Może dlatego, że używam starej wersji gcc