Подтвердить что ты не робот

Я могу вызвать метод без передачи необходимых аргументов в С++. Как так?

Вот код...

#include "stdafx.h"
#include<iostream>
using namespace std;

class Base
{
public:
    virtual void Display(bool b = false)
    {
        cout<<"Base"<<"\t"<<b<<endl;
    }
};

class Derived : public Base
{
public:
    virtual void Display(bool b) override
    {
        cout<<"Derived"<<"\t"<<b<<endl;
    }
};

int _tmain(int argc, _TCHAR* argv[])
{
    Base* bp = new Base();
    Derived* dp = new Derived();
    bp->Display();
    dp->Display(true);
    bp = new Derived();
    bp->Display();
    cout<<"Done"<<endl;
    return 0;
}

Когда метод Display() второй раз использует bp, он неожиданно попадает в метод в классе Derived. в классе Derived я не указал аргумент по умолчанию. Но он принял аргумент базового класса по умолчанию. Как?

4b9b3361

Ответ 1

Это удивляет немало людей, но аргумент по умолчанию (или аргументы, если вы указали более одного) на основе статического типа (тип, на который объявлен указатель), а не динамический тип ( тип объекта, к которому он в настоящее время указывает).

Как таковой, поскольку вы используете Base *bp, используются аргументы по умолчанию, объявленные в Base, независимо от того, указывает ли bp на Base или Derived.

Если вам небезразлично, почему это так: по крайней мере, в типичной реализации аргументы по умолчанию фактически обрабатываются во время компиляции. Компилятор видит, что вы вызвали Display без предоставления аргумента, и что Display имеет один аргумент со значением по умолчанию. Поэтому, когда он генерирует код для этого вызова, генерируется код для передачи заданного по умолчанию значения. В то время у него нет возможности даже догадываться, указывает ли указатель на некоторый производный тип, когда происходит вызов, поэтому все, что он может сделать, это генерировать код на основе статического типа. Хотя это не так, когда он генерирует код для выполнения вызова, даже возможно, что он может работать на производном классе, который еще не был спроектирован или написан, поэтому используйте значение, указанное в этом производном классе было бы невозможно.