2009-09-27 15 views
7

jestem w obliczu problemu w C++:C++ Problem przesłanianie/przeciążenie

#include <iostream> 

class A 
{ 
protected: 
    void some_func(const unsigned int& param1) 
    { 
    std::cout << "A::some_func(" << param1 << ")" << std::endl; 
    } 
public: 
    virtual ~A() {} 
    virtual void some_func(const unsigned int& param1, const char*) 
    { 
    some_func(param1); 
    } 
}; 

class B : public A 
{ 
public: 
    virtual ~B() {} 
    virtual void some_func(const unsigned int& param1, const char*) 
    { 
    some_func(param1); 
    } 
}; 

int main(int, char**) 
{ 
    A* t = new B(); 
    t->some_func(21, "some char*"); 
    return 0; 
} 

używam g ++ 4.0.1 i błąd kompilacji:

$ g++ -W -Wall -Werror test.cc 
test.cc: In member function ‘virtual void B::some_func(const unsigned int&, const char*)’: 
test.cc:24: error: no matching function for call to ‘B::some_func(const unsigned int&)’ 
test.cc:22: note: candidates are: virtual void B::some_func(const unsigned int&, const char*) 

Dlaczego muszę wskazać, że wywołanie some_func (param1) w klasie B to A :: some_func (param1)? Czy jest to błąd g ++ lub przypadkowa wiadomość z g ++, aby zapobiec przypadkom specjalnym, których nie widzę?

+0

To dziwne. Zabezpieczona funkcja klasy podstawowej powinna być widoczna dla podklasy, wirtualna, przeciążona lub nie. –

Odpowiedz

11

Problem polega na tym, że w klasie pochodnej ukrywasz metodę chronioną w klasie bazowej. Można zrobić kilka rzeczy, albo w pełni kwalifikuje się do chronionego obiektu w sposób pochodzącej albo przynieść tę metodę do zakresu z wykorzystaniem dyrektywy:

class B : public A 
{ 
protected: 
    using A::some_func; // bring A::some_func overloads into B 
public: 
    virtual ~B() {} 
    virtual void some_func(const unsigned int& param1, const char*) 
    { 
    A::some_func(param1); // or fully qualify the call 
    } 
}; 
+0

Dlaczego to ukrywam? Zastanawiam się nad drugim. Zwykle g ++ musi zachować sygnaturę przeciążonego init w tabeli v, ale tak nie jest. Dlaczego nie zachowuje podpisów każdej metody? Dlaczego traci on przeciążony (po prostu redefiniuję jedno z nich)? – fedj

+1

Po zdefiniowaniu metody o nazwie w klasie pochodnej, ukryje ona wszystkie inne metody o tej samej nazwie w hierarchii. Kiedy kompilator stwierdzi, że wywołujesz 'some_func' przez referencję typu statycznego B, spróbuje dopasować go do wszystkich wystąpień' some_func' w obrębie samego B i nie będzie próbował eskalować hierarchii, aby znaleźć możliwe dopasowania w klasach bazowych. –

+0

Czy jest to domyślne zachowanie g ++, aby uniknąć dużych rozmiarów tabel vtable lub czy jest to definicja C++, a każdy kompilator spowoduje ten sam błąd? Ponieważ normalnie, jeśli nie było przeciążenia w klasie A (powiedzmy inną nazwę metody), podpis zostałby skopiowany w vtable klasy B. – fedj