Перегрузка функции суперкласса

Есть ли что-то в стандарте С++, что мешает мне перегрузить функцию суперкласса?

Начиная с этой пары классов:

class A {            // super class
    int x;

public:
    void foo (int y) {x = y;}  // original definition
};

class B : public A { // derived class
    int x2;

public:
    void foo (int y, int z) {x2 = y + z;}  // overloaded
};

Я могу легко позвонить B::foo():

    B b;
    b.foo (1, 2);  // [1]

Но если я попытаюсь позвонить A::foo()...

    B b;
    b.foo (12);    // [2]

... Я получаю ошибку компилятора:

test.cpp: In function 'void bar()':
test.cpp:18: error: no matching function for call to 'B::foo(int)'
test.cpp:12: note: candidates are: void B::foo(int, int)

Просто чтобы убедиться, что я ничего не упустил, я изменил имя функции B, чтобы не было перегрузки:

class B : public A {
    int x2;

public:
    void stuff (int y, int z) {x2 = y + z;}  // unique name
};

И теперь я могу вызвать A::foo(), используя второй пример.

Это стандарт? Я использую г++.


person chrisaycock    schedule 04.01.2011    source источник


Ответы (2)


Вам нужно использовать объявление using внутри определения класса B:

class B : public A {
public:
    using A::foo;          // allow A::foo to be found
    void foo(int, int);
    // etc.
};

Без объявления using компилятор находит B::foo во время поиска имени и фактически не ищет в базовых классах другие объекты с таким же именем, поэтому A::foo не найден.

person James McNellis    schedule 04.01.2011
comment
чтобы скрыть исходную функцию-член. - person Nikolai Fetissov; 04.01.2011
comment
+1 - обратите внимание, что это описано (более подробно) в статье Скотта Мейерса «Эффективный С++», пункт 33: избегайте скрытия унаследованных имен. - person Billy ONeal; 04.01.2011

Вы не переопределяете реализацию A::foo(int), вместо этого вы используете псевдоним A::foo и меняете его подпись на (int,int) вместо (int). Как упомянул Джеймс Макнеллис, объявление using A::foo; делает доступной функцию из A.

person John Percival Hackworth    schedule 04.01.2011
comment
ОП не говорил о переопределении, он сказал о перегрузке, а перегрузка - это то, что он делает. Переопределение применяется к виртуальным функциям. - person Fred Nurk; 04.01.2011
comment
То, что он пытался сделать, было перегрузкой. То, что он сделал вместо этого, было чем-то вроде переопределения, но с дополнительным бонусом в виде псевдонима исходного метода. Как отметил Джеймс Макнеллис, оператор using решает проблему, допуская перегрузку. - person John Percival Hackworth; 04.01.2011