动态强制转换引用和自动转换
dynamic cast a reference and auto
我在使用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没有推导出正确的类型还是怎么的?
我还发现了一个肮脏的伎俩,仍然使用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:
因此,为了熟悉这个过程,看看用于推断当使用占位符类型声明的变量初始化时[…]推导出的返回类型或变量类型由类型确定它的初始化式。设
T
为变量的声明类型或者函数的返回类型。如果占位符是auto
类型说明符,则使用的规则确定推断的类型模板参数推导。[…]从T
中获取P
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);
现在,P
是U&
:
template <typename U>
void f(U&);
当然, U
仍然被推断为Derived
,但P
的类型(实际上是buffer
的类型)是Derived&
。
相关文章:
- 强制转换为引用类型
- 如何将 int 引用安全地转换为长引用?
- C 样式转换引用
- 将通用引用强制转换为可调用的 void 指针,反之亦然
- 隐式重新解释引用时强制转换,没有警告/错误
- 右值引用转换后的地址更改
- 通过引用传递参数时C++类型转换
- 为什么我需要在转换构造函数上引用 this->?
- 枚举类的 C 样式强制转换到基础类型 char 的引用
- 转换指针引用的字符串
- 隐式可转换参数,但属于引用类型
- 转换引用对象的边界框?
- C++将引用转换为指针?
- C++ 引用是否在需要时隐式转换为值?
- 如果可能的话,C++总是更喜欢右值引用转换运算符而不是常量左值引用吗?
- 返回对常量结构(指针类型)成员的引用:明显的左值到右值转换
- 从基类的共享指针向下转换到派生类的引用
- 为什么 const 允许在参数中隐式转换引用
- 与强制类型转换指针相比,在dynamic_cast中使用强制类型转换引用
- 动态强制转换引用和自动转换