Rozdzielczość przeciążenia C++ [duplikat]
To pytanie ma już odpowiedź tutaj:
Biorąc pod uwagę poniższy przykład, dlaczego muszę jawnie używać instrukcji b->A::DoSomething()
, a nie tylko b->DoSomething()
?
Czy rozdzielczość przeciążenia kompilatora nie powinna rozgryźć, o jakiej metodzie mówię?
I ' m korzystanie z Microsoft VS 2005. (Uwaga: korzystanie z wirtualnego nie pomaga w tym przypadku.)
class A
{
public:
int DoSomething() {return 0;};
};
class B : public A
{
public:
int DoSomething(int x) {return 1;};
};
int main()
{
B* b = new B();
b->A::DoSomething(); //Why this?
//b->DoSomething(); //Why not this? (Gives compiler error.)
delete b;
return 0;
}
9 answers
Dwa "przeciążenia" nie są w tym samym zakresie. Domyślnie kompilator rozważa tylko najmniejszy możliwy zakres nazw, dopóki nie znajdzie dopasowania nazw. Dopasowanie argumentów jest wykonywane później. W Twoim przypadku oznacza to, że kompilator widzi B::DoSomething
. Następnie próbuje dopasować listę argumentów, co nie powiedzie się.
Jednym z rozwiązań byłoby ściągnięcie przeciążenia z A
do zakresu B
:
class B : public A {
public:
using A::DoSomething;
// …
}
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
2008-09-16 13:18:27
Overload resolution to jedna z najbrzydszych części C++
Zasadniczo kompilator znajduje nazwę pasującą do "DoSomething (int)" w zakresie B, widzi, że parametry nie pasują i zatrzymuje się z błędem.
Można go pokonać używając a:: DoSomething w klasie B
class A
{
public:
int DoSomething() {return 0;}
};
class B : public A
{
public:
using A::DoSomething;
int DoSomething(int x) {return 1;}
};
int main(int argc, char** argv)
{
B* b = new B();
// b->A::DoSomething(); // still works, but...
b->DoSomething(); // works now too
delete b;
return 0;
}
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
2008-09-16 13:18:43
Nie, to zachowanie jest obecne, aby upewnić się, że nie zostaniesz przyłapany na dziedziczeniu z odległych klas bazowych przez pomyłkę.
Aby to obejść, musisz powiedzieć kompilatorowi, którą metodę chcesz wywołać, umieszczając a używając metody a:: DoSomething w klasie B.
Zobacz Ten artykuł aby uzyskać szybki i łatwy przegląd tego zachowania.
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
2008-09-16 13:27:02
Obecność metody w klasie pochodnej ukrywa wszystkie metody o tej samej nazwie (niezależnie od parametrów) w klasach bazowych. Robi się to, aby uniknąć takich problemów:
class A {} ;
class B :public A
{
void DoSomething(long) {...}
}
B b;
b.DoSomething(1); // calls B::DoSomething((long)1));
Niż później ktoś zmienia klasę A:
class A
{
void DoSomething(int ) {...}
}
Teraz nagle:
B b;
b.DoSomething(1); // calls A::DoSomething(1);
Innymi słowy, gdyby to nie działało w ten sposób, niepowiązana zmiana w klasie, której nie kontrolujesz (A), mogłaby w milczeniu wpłynąć na działanie Twojego kodu.
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
2017-11-21 16:03:17
To ma coś wspólnego ze sposobem, w jaki działa rozdzielczość nazw. Zasadniczo najpierw znajdujemy zakres, z którego pochodzi nazwa, a następnie zbieramy wszystkie przeciążenia dla tej nazwy w tym zakresie. Jednak zakres w Twoim przypadku to klasa B, a w klasie B, B::DoSomething ukrywa A::DOSomething:
3.3.7 ukrywanie nazw [basic.zakres.ukrywanie]
...[snip]...
3 w definicji funkcji member deklaracja nazwy lokalnej ukrywa na deklaracja członka klasy o tej samej nazwie; zobacz podstawowe.zakres.klasa . Deklaracja członka w klasie pochodnej (Klasa.derived ) ukrywa deklarację członka klasy bazowej ta sama nazwa; zob. Klasa .członek.lookup .
Z powodu ukrywania nazwy, a:: DoSomething nie jest nawet brane pod uwagę dla rozdzielczości przeciążenia
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
2008-09-16 13:30:17
Kiedy zdefiniujesz funkcję w klasie pochodnej, to ukryje ona wszystkie funkcje o tej nazwie w klasie bazowej. Jeśli funkcja klasy bazowej jest wirtualna i ma zgodny podpis, to funkcja klasy pochodnej również nadpisuje funkcję klasy bazowej. Nie wpływa to jednak na widoczność.
Możesz uczynić funkcję klasy bazowej widoczną za pomocą deklaracji using:
class B : public A
{
public:
int DoSomething(int x) {return 1;};
using A::DoSomething;
};
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
2008-09-16 13:19:23
To nie przeciążenie! To się ukrywa!
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
2010-01-23 18:22:56
Podczas wyszukiwania w drzewie dziedziczenia funkcji, C++ używa nazwy bez argumentów, po znalezieniu definicji zatrzymuje się, a następnie bada argumenty. W podanym przykładzie zatrzymuje się w klasie B. Aby móc robić to, czego szukasz, Klasa B powinna być zdefiniowana w następujący sposób:
class B : public A
{
public:
using A::DoSomething;
int DoSomething(int x) {return 1;};
};
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
2008-09-16 13:19:24
Funkcja jest ukryta przez funkcję o tej samej nazwie w podklasie (ale z innym podpisem). Możesz go odkryć, używając instrukcji using, jak w użyciu:: DoSomething ();
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
2008-09-16 13:20:37