我需要以下代码才能工作:
class Parent{
public:
virtual void fun(){throw 0};
};
class Child:public Parent{
public:
virtual void fun(){/*Success*/};
};
Parent& getChild(){
return *(new Child());
}
void main(){
auto child=getChild();
child.fun();
}
但是由于某种原因,auto
会创建Parent
而不是Parent &
,这会正确使用派生的方法。有没有一种方法可以强制auto
创建引用而不是使用简单的实例?
答案 0 :(得分:0)
C ++标准说明从初始化值中扣除auto:
声明
[dcl.spec.auto]/1:
auto
和decltype(auto)
类型说明符用于指定占位符类型 以后由从初始值设定项中推导得出。初始化程序
[dcl.init]/1:
声明程序可以指定初始值 值(用于声明的标识符)。
因此,当您编写以下声明符时:
int t = f(10);
auto x = y;
auto child = getChild();
右边被评估为表达式,该表达式产生一个值。并且此值用于初始化在左侧声明的变量。
值不是参考。它不像指针和地址。在表达式评估中,每当使用引用时,都要考虑引用值。您可以通过以下简单的代码段看到它:
int x=15;
int&y = x;
cout << x <<", " << y <<", " << &x<<endl;
cout << typeid(x).name() <<", " << typeid(y).name() <<", " << typeid(&x).name() <<endl;
在您的情况下,表达式值因此是Parent
而不是Parent &
。这就是为什么您的auto
被推导为Parent
类型的原因。
但是,C ++标准并未以相同方式考虑所有值。在[basic.lval]
中,它对不同类型的值(可以是 lvalues , xvalues 和 prvalues )进行了重要区分。在您的情况下,getChild()
得出的左值是您引用的对象,而不是它的某些临时副本。
具有这样的左值时,可以创建对其的引用:
[dcl.ref]
/ 2:使用&
声明的引用类型称为 左值引用,(...)
但是您需要明确地做到这一点,说您的汽车应该是一个参考:
auto &child = getChild();
编辑: 有关自动工作方式的更多信息:Herb Sutter's GotW blog