2015-02-14 2 views
2
#include <bits/stdc++.h> 
using namespace std; 

class Base { 
    public: 
    virtual int function() const { 
    cout << "Base::function()\n"; 
    return 1; 
    } 
    virtual void function(string) const {} 
}; 


class Derived : public Base { 
    public: 
     // overloading function() of base 
     int function(int) const { 
     cout << "Derived::function()\n"; 
     return 4; 
    } 
}; 


int main() 
{ 
    string s("StackOverflow"); 
    Derived d; 
    Base* b = &d; 
    //calling derived::function() and function(s)  
    b->function(); 
    b->function(s); 
} 

Из-за перегрузки, имя скрывается в производном происходить подавление класса.
Из-за ключевого слова виртуальный во время исполнения Derived :: function() должен вызываться.перегрузки виртуальной функции и вызов функции, полученной с помощью указателя базового класса

Но код успешно компилируется. ссылка: http://ideone.com/fbVm0P
В чем причина этого странного поведения?
EDIT 1:

d.function(); 
d.function(s); 

не обобщать, как и ожидалось.

+0

Tangent: Почему вы включаете <бит/stdC++. H>? Это не предназначено для потребления пользователями, поскольку это внутренняя деталь реализации G ++. –

+2

Вы вызываете базовый указатель, поэтому скрытие имени не имеет значения. –

+0

У вас нет производной 'function()' у вас есть только не производная функция (int) '. Параметры имеют значение. Различные параметры означают разную функцию. – Galik

ответ

3

разрешения перегрузки использует статические типы (не то, что он будет делать разницы здесь). Таким образом, оба b->function() и b->function(s) разрешают Base::function, без ошибок. Наконец, поскольку эти функции были объявлены virtual, окончательное разрешение будет принимать во внимание любые перегрузки в производном классе. Но их нет, поэтому будет вызываться функция в базовом классе.

Скрытие имени происходит во время поиска имени, которое находится перед перегрузкой , а также относится только к статическому типу; в выражении , например b->function() или b->function(s), компилятор полностью игнорирует Derived; он выполняет поиск имени по статическому типу. Название скрыть будет только статический тип: Derived; после того, как компилятор нашел function в Derived, это было бы .

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

+0

«Скрытие имени происходит во время поиска имени, которое до переопределения разрешения» может быть более понятным. Это правда, что компиляция происходит до запуска программы. Но действительно ли это то, что вы пытаетесь сказать? –

+0

@Alf Я хотел сказать, что поиск имени происходит до разрешения _overload_. (Оба из них являются временем компиляции.) Я исправил это; Благодарю. –

2

В производном классе нет int function() const.

Используйте override ключевое слово, чтобы избежать сюрпризов, как это, то есть,

class Derived 
    : public Base 
{ 
public: 
    // not overriding function() of base 
    auto function(int) const 
     -> int override // This won't compile, because it doesn't override. 
    { 
     cout << "Derived::function()\n"; 
     return 4; 
    } 
}; 
+0

'В производном классе нет функции int function().« Именно поэтому она должна давать ошибку времени выполнения, но код работает отлично. и я ** не хочу, чтобы oerride **. просто делая это для обучения цели. –

+0

@aseem: пожалуйста, объясните, почему вы считаете, что ошибка во время выполнения должна быть результатом отказа от переопределения функции. –

+0

Во время компиляции 'C++' делает проверку типов и т. Д. On' Base :: int function() ', поскольку она фактически находится внутри Base.During во время выполнения из-за' virtual' компилятора будет искать 'Derived :: int function()' которая на самом деле не видна из-за скрытия имени. –

Смежные вопросы