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;
}
Author: Peter Mortensen, 2008-09-16

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;
    // …
}
 40
Author: Konrad Rudolph,
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;
}
 14
Author: Pieter,
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.

 5
Author: Lehane,
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.

 5
Author: James Curran,
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

 3
Author: Arkadiy,
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;
};  
 2
Author: Anthony Williams,
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!

 2
Author: ugasoft,
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;};  
}; 
 1
Author: Jono,
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 ();

 1
Author: slicedlime,
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