Каковы правила для поиска виртуальных функций? - PullRequest
5 голосов
/ 21 марта 2011
#include <iostream>
class base
{
    public:
    virtual void print (int a)
    {   
        std::cout << "a: " << a << " base\n";
    }   
    virtual void print (int a, int b)
    {   
        std::cout << "base\n";
    }   
};

class derived : public base
{
    public:
    virtual void print (double d)
    {   
        std::cout << "derived\n";
    }   
};

int main ()
{
    int i = 10; 
    double d = 10000.0;
    base *b = new derived (); 
    b->print (i, i); 
    b->print (d);

    return 0;
}

Вывод этой функции:

base
a: 10000 base
  • Почему b->print (d) не вызывает реализацию производного класса и выполняет статическое приведение к 'd' для обеспечения соответствия среализация базового класса?
  • Какое правило применяется здесь при поиске виртуальной функции?

Ответы [ 3 ]

8 голосов
/ 21 марта 2011

derived::print не переопределяет любую функцию-член в base.Он объявляется как имеющий единственный параметр типа double, но две виртуальные функции-члены с именем print в base объявляются как имеющие один и два параметра типа int.

Когда вы используетеb->print(d), только функции-члены в base рассматриваются при разрешении перегрузки, поэтому учитываются только void base::print(int) и void base::print(int, int).void derived::print(double) не может быть найден, потому что компилятор не знает, что b указывает на объект derived.

Если derived переопределит одну из двух print функций, объявленных как виртуальныефункции-члены в base, тогда это переопределение будет вызываться во время выполнения.

(В некотором родственном примечании derived::print скрывает две base::print функции-члена, поэтому если вы попытаетесь использовать одну из нихиз функций базового класса print, например, derived().print(1, 1), произойдет сбой. Вам нужно будет использовать объявление using, чтобы сделать эти функции-члены доступными во время поиска по имени.)

1 голос
/ 21 марта 2011

Разрешение перегрузки происходит во время компиляции.Переопределения происходят во время выполнения.

Следовательно, разрешение перегрузки b->print(d); происходит первым.Это выбирает Base::print(int), потому что это единственный аргумент print.

Во время выполнения b указывает на объект Derived, который не имеет переопределения для Base::print(int).Следовательно, Base::print(int) все еще называется.

0 голосов
/ 21 марта 2011

Поскольку double можно автоматически преобразовать в int в первом определении, которое он видит (в базовом классе)

См. Ключевое слово explicit или этот вопрос

...