c++ - 添加字符串类型的类成员会导致调用基类函数而不是子类
问题描述
为什么下面的代码打印 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 语句也是如此,尽管我不明白为什么其中任何一个都是真的。
编辑:这似乎是由于一个悬空指针。那么在 C++ 中在 Java 中做这样的事情的标准模式是什么:
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;
}
TL;DR 解决方案
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
。
但最好避免原始动态分配,因此我们可以进行另一项改进:使用智能指针。
这让我们回到了解决方案。
推荐阅读
- spring - Spring Cloud Gateway 2.0.0.RELEASE:找不到名称为 Hystrix 的 GatewayFilterFactory
- vue.js - 尝试使用带有 vuejs 的按钮更新组件
- caching - Laravel 5.5:委托这个缓存存储不支持标记?
- php - 提交价格表单请求后未捕获的错误
- javascript - 创建一个接受时间范围对象输入并返回合并时间范围对象数组的组件 javascript
- sqlite - 如何修复 Xamarin.Forms 中的 DateTime 更新问题?
- java - 避免点击后vaadin网格自动水平滚动
- kubernetes - Kubernetes:角色与集群角色
- kubernetes - Kubernetes 集群中 CPU 内核使用率高(84%)
- javascript - React JSX highcharts 不会更新