C++11 在 class 中存储多态对象的方式
C++11 way of storing a polymorphic object in a class
在 C++11 之前,我会实现一个 class Foo,包含一个 base-class Bar 的多态对象:
struct Foo {
Bar* m_b;
Foo(Bar* b) : m_b(b) {}
};
根据 Scott Meyer 关于原始指针不好的建议,我想以 C++11 的方式实现 Foo
,但我不知道这会是什么样子。
我开始写得像
struct Foo {
std::unique_ptr<Bar> m_b;
Foo(std::unique_ptr<Bar> b) : m_b(std::move(b)) {}
};
但这有缺点b
必须动态分配。
那么实现包含多态对象的 class 的 C++11 方法是什么?
智能指针优于原始指针的论点是基于所有权的。
资源的所有权应该从类型系统中明确,因为它很容易出错,而仅通过阅读代码很难理解。将其嵌入到类型系统中后,您就可以从对象的类型中判断是什么决定了对象的生命周期。
C++11 之前的代码要么不拥有 Bar
(它不对其生命周期负责),要么您的代码泄露了。
post-C++11 代码拥有 Bar
并负责其生命周期。
如果你想要一个 Foo
有条件地拥有 Bar
基于可能复杂的运行时逻辑的状态,而有时却没有,那么 std
智能指针可能不是好主意。
想象一下,在汽车安全规则出台之前你有一辆汽车。它有一个按钮,可以将乘客从车里弹出。这很有趣,只要您不按下按钮,就很安全。
现在有汽车安全规则,您听说要遵守这些规则 "better"。您来到汽车安全问答环节,询问如何设置一个按钮将您的乘客从汽车中弹出并遵守这些汽车安全规则。他们似乎不允许乘客弹射。即使你在按钮上盖上盖子,也有一些关于 "what if the car gets in an accident and the button executes incorrectly" 和生命、肢体和其他东西的东西。
如何在我的汽车中安装弹射座椅并获得 5 星安全评级?
智能指针使所有权清晰。如果你混淆了所有权,那么你必须弄清楚它才能使用智能指针。
有些情况证明复杂的所有权和生存期语义是合理的。这些很少见,通过默认使用智能指针,我们可以避免生命周期的复杂性 而不必每次都验证它 .
struct Foo {
std::unique_ptr<Bar> m_b;
Foo(std::unique_ptr<Bar> b) : m_b(std::move(b)) {}
};
这是一个更好的接口,因为 Foo
的构造函数明确表示它拥有所有权。拿一个原始指针,然后用智能指针包裹起来,界面不清晰。
在 C++11 之前,我会实现一个 class Foo,包含一个 base-class Bar 的多态对象:
struct Foo {
Bar* m_b;
Foo(Bar* b) : m_b(b) {}
};
根据 Scott Meyer 关于原始指针不好的建议,我想以 C++11 的方式实现 Foo
,但我不知道这会是什么样子。
我开始写得像
struct Foo {
std::unique_ptr<Bar> m_b;
Foo(std::unique_ptr<Bar> b) : m_b(std::move(b)) {}
};
但这有缺点b
必须动态分配。
那么实现包含多态对象的 class 的 C++11 方法是什么?
智能指针优于原始指针的论点是基于所有权的。
资源的所有权应该从类型系统中明确,因为它很容易出错,而仅通过阅读代码很难理解。将其嵌入到类型系统中后,您就可以从对象的类型中判断是什么决定了对象的生命周期。
C++11 之前的代码要么不拥有 Bar
(它不对其生命周期负责),要么您的代码泄露了。
post-C++11 代码拥有 Bar
并负责其生命周期。
如果你想要一个 Foo
有条件地拥有 Bar
基于可能复杂的运行时逻辑的状态,而有时却没有,那么 std
智能指针可能不是好主意。
想象一下,在汽车安全规则出台之前你有一辆汽车。它有一个按钮,可以将乘客从车里弹出。这很有趣,只要您不按下按钮,就很安全。
现在有汽车安全规则,您听说要遵守这些规则 "better"。您来到汽车安全问答环节,询问如何设置一个按钮将您的乘客从汽车中弹出并遵守这些汽车安全规则。他们似乎不允许乘客弹射。即使你在按钮上盖上盖子,也有一些关于 "what if the car gets in an accident and the button executes incorrectly" 和生命、肢体和其他东西的东西。
如何在我的汽车中安装弹射座椅并获得 5 星安全评级?
智能指针使所有权清晰。如果你混淆了所有权,那么你必须弄清楚它才能使用智能指针。
有些情况证明复杂的所有权和生存期语义是合理的。这些很少见,通过默认使用智能指针,我们可以避免生命周期的复杂性 而不必每次都验证它 .
struct Foo {
std::unique_ptr<Bar> m_b;
Foo(std::unique_ptr<Bar> b) : m_b(std::move(b)) {}
};
这是一个更好的接口,因为 Foo
的构造函数明确表示它拥有所有权。拿一个原始指针,然后用智能指针包裹起来,界面不清晰。