2009-09-27 2 views
7

Я столкнулся с проблемой в C++:C++ проблемы переопределения/перегрузки

#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; 
} 

Я использую г ++ 4.0.1 и ошибку компиляции:

$ 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*) 

Почему я должен указать, что вызов some_func (param1) в классе B - A :: some_func (param1)? Это ошибка g ++ или случайное сообщение из g ++ для предотвращения особых случаев, которые я не вижу?

+0

Это странно. Защищенная функция базового класса должна быть видимой для подкласса, виртуальной, перегруженной или нет. –

ответ

11

Проблема в том, что в производном классе вы скрываете защищенный метод в базовом классе. Вы можете сделать пару вещей: либо вы полностью квалифицируете защищенный метод в производном объекте, либо вы вводите этот метод в область действия с помощью директивы using:

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

Почему я его скрываю? Я просто переопределяю второй. Обычно g ++ должен содержать подпись перегруженного init в таблице v, но это не так. Почему он не поддерживает подписи каждого метода? Почему он потерял перегруженный (я просто переопределяю один из них)? – fedj

+1

Когда вы определяете метод с именем в производном классе, он будет скрывать все другие методы с тем же именем, что и в иерархии. Когда компилятор обнаруживает, что вы вызываете 'some_func' через ссылку статического типа B, он попытается сопоставить его со всеми вхождениями' some_func' внутри самого B и не будет пытаться эскалации иерархии для поиска возможных совпадений в базовых классах. –

+0

Это поведение g ++ по умолчанию, чтобы избежать больших размеров vtable или это определение C++, и каждый компилятор сделает ту же ошибку? Поскольку обычно, если это не было перегрузкой в ​​классе A (скажем, другим именем метода), подпись была бы скопирована в классе B vtable. – fedj