13

これがコードです...

#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()を使って 2 回目にメソッドを呼び出すと、なんとクラスbp内のメソッドにヒットしました。Derivedクラスでは、Derivedデフォルトの引数を指定しませんでした。しかし、デフォルトの基本クラスの引数を取りました。どのように?

4

1 に答える 1

21

これはかなりの数の人々を驚かせますが、デフォルトの引数 (複数指定した場合は引数) は、動的型 (の型現在たまたま指しているオブジェクト)。

そのため、 を使用しているため、がたまたま を指しているかを指しているかに関係なく、 でBase *bp宣言されているデフォルトの引数が使用されます。BasebpBaseDerived

これがなぜなのか気になる場合: 少なくとも典型的な実装では、デフォルトの引数は実際にはコンパイル時に完全に処理されます。コンパイラはDisplay、引数を指定せずに a を呼び出したこと、およびDisplayデフォルト値を持つ引数が 1 つあることを認識します。したがって、その呼び出しのコードを生成するときに、指定された既定値を渡すコードが生成されます。その時点では、呼び出しが行われたときにポインターが何らかの派生型を指している可能性があるかどうかを推測する方法さえないため、静的型に基づいてコードを生成することしかできません。ここではそうではありませんが、呼び出しを行うコードを生成するときに、まだ設計または作成されていない派生クラスで動作している可能性さえあるため、その派生クラスで指定された値を使用しますしません

于 2013-09-27T05:07:31.627 に答える