为什么下面的代码显示0,但是如果注释掉“ std :: string my_string”,则显示1?
#include <stdio.h>
#include <iostream>
class A {
public:
virtual int foo() {
return 0;
}
private:
std::string my_string;
};
class B : public A {
public:
int foo() {
return 1;
}
};
int main()
{
A* a;
if (true) {
B b;
a = &b;
}
std::cout << a->foo() << std::endl;
return 0;
}
我也理解将std :: string更改为std:string *也会导致代码显示1,就像删除if语句一样,尽管我不明白为什么其中任何一个都是正确的。
快点
编辑:这似乎是由于悬空的指针。那么,在Java中执行此类操作的C ++标准模式是什么:
Animal animal;
boolean isDog = false;
// get user input to set isDog
if (isDog) {
animal = new Dog();
} else {
animal = new Cat();
}
animal.makeNoise(); // Should make a Dog/Cat noise depending on value of isDog.
该程序具有未定义的行为。b
仅在身体的范围内if
。访问悬空指针时,不能指望逻辑结果。
int main()
{
A* a;
if (true) {
B b; // b is scoped by the body of the if.
a = &b;
} // b's dead, Jim.
std::cout << a->foo() << std::endl; // a points to the dead b, an invalid object
return 0;
}
int main()
{
std::unique_ptr<A> a; // All hail the smart pointer overlords!
if (true) {
a = std::make_unique<B>();
}
std::cout << a->foo() << std::endl;
return 0;
} // a is destroyed here and takes the B with it.
您可以指向a
具有动态生命周期的对象
int main()
{
A* a;
if (true) {
a = new B; // dynamic allocation
} // b's dead, Jim.
std::cout << a->foo() << std::endl;
delete a; // DaANGER! DANGER!
return 0;
}
不幸的delete a;
是,由于A
具有非virtual
析构函数,因此也是未定义的行为。如果没有虚拟析构函数,则所指向的对象a
将被破坏为A
而不是B
。
解决方法是提供A
一个虚拟析构函数,使其能够销毁正确的实例。
class A {
public:
virtual ~A() = default;
virtual int foo() {
return 0;
}
private:
std::string my_string;
};
无需修改,B
因为一旦声明了函数virtual
,该函数将保留virtual
其子代。密切注意final
。
但是最好避免原始的动态分配,因此我们可以做更多的改进:使用智能指针。
这使我们回到了解决方案。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句