我正在使用 C++0X 标准中的自动功能,但我对如何做出类型决定感到困惑。考虑以下代码。
struct Base
{
virtual void f()
{
std::cout << "Base::f" << std::endl;
}
};
struct Derived : public Base
{
virtual void f()
{
std::cout << "Derived::f" << std::endl;
}
};
int main()
{
Base* dp = new Derived;
auto b1 = *dp;
auto& b2 = *dp;
std::cout << typeid(b1).name() << std::endl;
std::cout << typeid(b2).name() << std::endl;
}
它将打印 Base 和 Derived。
但是为什么 auto&
被评估为对 Derived 的引用而不是对 Base 的引用?
更糟糕的是把代码改成这样:
struct Base{};
struct Derived : public Base{};
int main()
{
Base* dp = new Derived;
auto b1 = *dp;
auto& b2 = *dp;
std::cout << typeid(b1).name() << std::endl;
std::cout << typeid(b2).name() << std::endl;
}
返回两种类型的 Base。那么为什么类型依赖于虚函数呢? 我使用的编译器是VS2010。 谁能给我一个提示,我可以在标准中找到这种行为的定义吗?
最佳答案
auto
在这两种情况下都会产生 Base
,而不是派生的。在第一种情况下,您正在对对象进行切片(在父级别复制),而在第二种情况下,因为它是一个引用,所以您会得到一个 Base&
到实际的 Derived
目的。这意味着所有虚函数调用都将被分派(dispatch)到 Derived
级别的最终覆盖器。
typeid
运算符对多态类型的行为与对非多态类型的行为不同。如果应用于对多态类型的引用,它将在运行时执行类型检查并产生实际对象的类型。如果它应用于对象或对非多态类型的引用,它将在编译时解析为对象或引用的静态类型。
要验证 auto
推断的内容,您可以使用稍微不同的测试:
void test( Base& ) { std::cout << "Base" << std::endl; }
void test( Derived& ) { std::cout << "Derived" << std::endl; }
然后调用该函数并查看它解析为什么类型。我希望编译器选择第一个重载,因为 auto& a = *dp;
应该等同于 Base& a = *dp;
关于c++ - 在 C++0X 中评估 auto 的类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6706794/