虚拟方法与标准默认参数

时间:2015-08-09 18:54:16

标签: c++

想象一下以下场景

public sealed class FixedWidth96Converter : ConverterBase
{
    public override string FieldToString(object from)
    {
        string val = from as string;
        if (!string.IsNullOrWhiteSpace(val))
        {
            return val.PadLeft(96, ' ');
        }
        return base.FieldToString(from);
    }

    public override object StringToField(string from)
    {
        return from;
    }
}

输出非常明确:2和2由于虚拟和向下转换(从基础到孩子)。

但是,在代码中进行一些更改,如:

class B
{
public:
    int n;
    B() { n = 1;};
    virtual int shift() const { return n; }
};

class D : public B
{
public:
    D() { n = 2;};
    int shift() const { return n; }
};

int main()
{
    D d;

    std::cout << d.shift() << std::endl;

    B *b = &d;

    std::cout << b->shift() << std::endl;

    std::cin.get();

    return 0;
}

并保持相同的main(),我们的输出将是:2和1.为什么&#34; 1&#34;如果方法是虚拟的?

非常感谢!

2 个答案:

答案 0 :(得分:0)

在本声明中

std::cout << b->shift() << std::endl;

编译器根据指针B的静态类型使用类b中函数的声明,并使用相应的默认参数。

首先,编译器会计算函数的参数,而这个参数是声明

的默认参数
virtual int shift(int n = 1) const { return n; }

然后使用动态绑定并调用类D中的函数。:)

尝试以下示例

#include <iostream>

int main()
{
struct B
{
    virtual ~B() = default;
    virtual int shift(int n = 1) const { std::cout << "B::shift( int ): "; return n; }
};

struct D : B
{
    virtual int shift(int n = 2) const { std::cout << "D::shift( int ) : "; return n; }
};
    D d;
    B *b = &d;

    std::cout << b->shift() << std::endl;
}    

你会得到

D::shift( int ) : 1
^^^               ^^^ 

即编译器根据指针shift的静态类型搜索类B范围内的名称b。但是使用动态绑定机制从类D调用函数。

答案 1 :(得分:-1)

显然,编译器在函数名称的修改中使用默认参数值。

上述评论中的副本提供了另一个原因。编译器在编译时解析默认参数。