动态转换引用和自动

时间:2015-07-25 15:59:03

标签: c++ c++11 reference auto dynamic-cast

使用auto和dynamic_cast时,我遇到了一个非常奇怪的行为。 这是我的课程:

class BaseInterface {
public:
    virtual void someMethod()=0;
};

class Derived:public BaseInterface {
public:
    virtual void someMethod1()=0;
    void someMethod()override;
};

当然,有些类可以实现所有派生方法。

然后有第三个类看起来像这样:

class ThirdClass {
public:
    void demoMethod(BaseInterface&);
    void anotherMethod(Derived&);
};

void ThirdClass::demoMethod(BaseInterface& obj) {
    auto buffer=dynamic_cast<Derived&>(obj);
    anotherMethod(buffer);
}

当我使用gcc编译它时,我得到一个“无法分配抽象类型的对象”错误。而当我替换

auto buffer=...

Derived& buffer=...

一切都很好。为什么会这样?自动没有推断出正确的类型或什么?

此外,我发现仍然使用auto的肮脏技巧:

void ThirdClass::demoMethod(Base& obj) {
    auto buffer=dynamic_cast<Derived*>(&obj);
    anotherMethod(*buffer);
}

2 个答案:

答案 0 :(得分:6)

您从Derived获得auto。请改用:

auto & buffer = dynamic_cast<Derived&>(obj);

答案 1 :(得分:4)

§7.1.6.4/ 7:

  

初始化使用占位符类型声明的变量时[...]   推导出的返回类型或变量类型由类型确定   它的初始化程序。 [...]让T成为变量的声明类型   或返回函数的类型。 如果占位符是auto   type-specifier,推导出的类型是使用规则确定的   模板参数推导。 [...]通过替换P来获取T   使用新发明的类型模板发生auto   参数U [...]。 使用模板规则为U推算一个值   函数调用(14.8.2.1)中的参数推导,其中P是a   函数模板参数类型和相应的参数是   初始化程序。

因此,为了熟悉该过程,请查看用于推断buffer类型的实际规则:如果更改会发生什么

template <typename U>
void f( U );

void f( Derived& );

使用f类型的左值调用Derived时?显然,对于功能模板,U将被推断为Derived,然后产生扣减失败。
这与示例中扣除占位符类型直接对应 - auto将替换为Derived,但失败,因为Derived是抽象的。

一般来说,如果你写

auto obj = …;

obj永远不会成为参考,就像在调用上述函数模板时永远不会将U推断为引用类型一样。

相反,请使用auto&

auto& buffer = dynamic_cast<Derived&>(obj);

现在,PU&

template <typename U>
void f(U&);

U当然仍被推断为Derived,但P的类型 - 实际上是buffer的类型 - 是Derived&