2016-09-10 3 views
0

Вот два класса, которые перегружают виртуальную функцию:Как перегруженные виртуальные функции выбраны, когда нет никакого `используя Base_class :: function_name`

class Base 
{ 
public: 
    virtual void func(int) { 
     cout<<"base int"<<endl; 
    } 
    virtual void func(double) { 
     cout<<"base double"<<endl; 
    } 
}; 

class Deri: public Base 
{ 
public: 
    virtual void func(int) { 
     cout<<"deri int"<<endl; 
    } 
}; 

Я использую эти классы здесь:

int main() { 
    Base * ptr = new Deri; 
    ptr->func(3.0);      //"base double" 
    static_cast<Deri *>(ptr)->func(3.0);//"deri int" 
    return 0; 
} 

I ожидается, что оба вызова для базовой двойной перегрузки, но я получаю следующий вывод:

base double 
deri int 

Когда я добавляю следующее «используя» заявление в Deri:

using Base::func; 

Я получаю все перегруженные функции из класса Base, и она работает, как ожидалось.

Что происходит, когда я не использую эту «инструкцию использования»? Я предполагаю, что ptr->func(3.0) и static_cast<Deri*>->func(3.0) ищите ту же самую таблицу. Но как они ищут разные функции? Как выглядит vtable класса Deri?

+0

«* Я знаю, что мы обычно используем« используя », чтобы получить все перегруженные функции из базового класса. *« ... мы? –

+0

Предполагая, что 'ptr1' действительно означает' ptr'. – WhozCraig

+2

Вы можете найти это интересно: [Почему переопределенная функция в производном классе скрывает другие перегрузки базового класса?] (Https://stackoverflow.com/questions/1628768/why-does-an-overridden-function-in – WhozCraig

ответ

0

Посмотрите здесь: http://thesyntacticsugar.blogspot.ca/2011/10/behind-scenes-name-hiding-in-c.html

Он сказал, что «При определении возможных кандидатов, поиск имен распространяется наружу, начиная с непосредственной сферы только если функция не существует с правильным названием делает процесс перехода к следующему объема вмещающей. После определения области видимости, которая имеет хотя бы один жизнеспособный кандидат, компилятор продолжает сопоставлять аргументы с параметрами различных кандидатов, применяя правила доступа и т. Д. ».

Таким образом, мое понимание - это тип указателей, в которых начинается поиск имени. Когда он является указателем базового класса, он сначала ищет в базе классов. Когда static_cast относится к классу Deri, он сначала смотрит в Class Deri.

Примечательно, что все три версии func() находятся в таблице vtable класса Deri.