动态转换参考和自动

dynamic cast a reference and auto

我在使用 auto 和 dynamic_cast 时遇到了一个非常奇怪的行为。 这是我的 class 层次结构:

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

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

当然还有一些 class 实现所有派生方法。

然后是第三个 class 看起来像这样:

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

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

当我用 gcc 编译它时,出现 "cannot allocate an object of abstract type" 错误。而当我更换

auto buffer=...

Derived& buffer=...

编译一切正常。为什么会这样?是 auto 没有推导出正确的类型还是什么?

我还发现了一个仍然使用自动的肮脏技巧:

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

您正在从 auto 获得 Derived。改用这个:

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

§7.1.6.4/7:

When a variable declared using a placeholder type is initialized […] the deduced return type or variable type is determined from the type of its initializer. […] let T be the declared type of the variable or return type of the function. If the placeholder is the auto type-specifier, the deduced type is determined using the rules for template argument deduction. […] obtain P from T by replacing the occurrences of auto with either a new invented type template parameter U[…]. Deduce a value for U using the rules of template argument deduction from a function call (14.8.2.1), where P is a function template parameter type and the corresponding argument is the initializer.

因此,为了熟悉该过程,请看一下用于推导 buffer 类型的实际规则:如果更改

会发生什么
template <typename U>
void f( U );

void f( Derived& );

当使用 Derived 类型的左值调用 f 时?显然,对于函数模板,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&.