下面的参考变量foo使用的实例Foo或其Bar基于的派生类进行初始化condition。基于say()方法的输出,足够奇怪的是,它foo似乎是的实例,Foo而不是的实例Bar-为什么?
#include <iostream>
class Foo {
public:
virtual void say() const {
std::cout << "Foo\n";
}
};
class Bar : public Foo {
public:
virtual void say() const {
std::cout << "Bar\n";
}
};
int main() {
constexpr bool condition = false;
const Foo& foo = condition ? Foo() : Bar();
foo.say(); // outputs "Foo” ???
return 0;
}
Run Code Online (Sandbox Code Playgroud)
如果我注释每个构造函数,我可以看到Bar在评估三元表达式时会调用该构造函数。如果我注释每个析构函数,我会看到Bar析构函数在 foo初始化之前被调用-这告诉我Bar三元运算符创建了一个临时对象,但在初始化之前将其销毁了-为什么?
编译(Apple LLVM版本9.0.0(clang-900.0.39.2))
clang++ -Wall -std=c++11 foo.cpp -o foo
Run Code Online (Sandbox Code Playgroud)
问题所在
const Foo& foo = condition ? Foo() : Bar();
Run Code Online (Sandbox Code Playgroud)
就是两个部分都需要返回相同的类型。由于Foo()和Bar()不是同一类型,因此编译器会尝试将它们转换。它唯一可以做的有效转换就是将Bar()其切成薄片Foo。这意味着无论您得到什么,您都将对a的引用进行绑定,Foo并且该Bar零件消失。
要解决此问题,您需要使用类似
#include <iostream>
#include <memory>
class Foo {
public:
virtual ~Foo() = default; // don't forget to add this when using polymorphism
virtual void say() const {
std::cout << "Foo\n";
}
};
class Bar : public Foo {
public:
virtual void say() const {
std::cout << "Bar\n";
}
};
int main() {
constexpr bool condition = false;
auto foo = condition ? std::make_unique<Foo>() : std::make_unique<Bar>();
foo->say(); // outputs "Bar" now
return 0;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
50 次 |
| 最近记录: |