2015-07-21 1 views
2

В этом примере показан объект производного класса, передаваемый функции, которая ссылается на базовый класс в качестве параметра. Функция-член g(int) в производном классе скрывает g(float) в базовом классе. Я это понимаю, и мой вопрос не связан с этим.Передача производного объекта в качестве базового параметра базового класса

class Base { 
public: 
    virtual void g(float x) throw() 
    { 
     cout << "Base::g(float)\n"; 
    } 
}; 

class Derived : public Base { 
public:   
    virtual void g(int x) throw() // Bad: Hides Base::g(float) 
    { 
     cout << "Derived::g(int)\n"; 
    } 
}; 


void sampleTwo(Base& b, Derived& d) 
{ 
    b.g(3.14f); 
    d.g(3.14f); // Bad: Converts 3.14 to 3 and calls Derived::g(int) 
} 

int main() 
{ 
    Derived d; 
    sampleTwo(d, d); 
    return 0; 
} 

Выход:

Base::g(float) 
Derived::g(int) 

Мой вопрос с выходом "Base :: г (поплавок)". Поскольку объект, на который ссылается «b» в sampleTwo(), является производным объектом, не должно ли динамическое связывание вызывать метод g() производного класса (преобразование float в int)?

+0

При написании функции производного класса, чтобы переопределить виртуальный класс базового класса, отличная идея начать использовать ключевое слово 'override' (предполагая компилятор с разумной поддержкой C++ 11). Таким образом, компилятор может дать вам сообщение об ошибке, если функция на самом деле не переопределяется по своему усмотрению. – TheUndeadFish

+0

Я также удивлен, но моим первоначальным предположением было бы увидеть base :: g (float), вызываемый дважды, а не производный :: g (int), поскольку вызов функции в обоих случаях соответствует сигнатуре g (float), которая является другой функцией g (int) (это две разные функции, ваш код не делает переопределения) –

+0

Вы должны «использовать Base :: g» в 'Derived', чтобы отобразить' Base :: g (float) '. – WorldSEnder

ответ

1

Динамическая рассылка вызывает окончательный переезд. Начиная с Derived::g шкуры, а не переопределения Base::g, окончательный повод Base::g в Derived по-прежнему Base::g.

0

g(float) и g(int) - различные функции. Если вы хотите, чтобы Derived работал, вы должны использовать g(float) в обоих классах.

g() могут быть перегружены проверить перегрузку функции: https://en.wikipedia.org/wiki/Function_overloading

Пример (g(float) и g(int) в том же классе и отдельных функций):

class Derived : public Base { 
public: 

    void g(float x) throw(); 
    void g(int x) throw(); 

}; 
3

g(int) и g(float) две совершенно разные методы. Derived::g(int) не переопределяет Base::g(float). Эти методы не связаны.

С Derived не отменяет g(float), ваши ожидания относительно b.g(3.14f) являются необоснованными. Как и ожидалось, b.g(3.14f) должен позвонить Base::g(float).

Если вы переопределяете g(float) в Derived, то b.g(3.14f) действительно вызовет Derived::g(float).

+0

Thankyou. Понял это сейчас. – irappa