【发布时间】:2014-10-13 20:03:16
【问题描述】:
我有一个像这样的头文件foo.h(不相关的东西省略了):
#pragma once
#include <memory>
class Bar;
struct Foo
{
std::shared_ptr<Bar> getBar();
std::shared_ptr<const Bar> getBar() const
{
return const_cast<Foo*>(this)->getBar();
}
};
getBar() 的非常量重载在一个 .cpp 文件中实现,该文件还可以看到 Bar 的完整定义。
当foo.h 包含在另一个文件中(没有看到Bar 的定义)时,VS 2010 会给出这样的警告:
warning C4150: deletion of pointer to incomplete type 'Bar'; no destructor called
getBar() 的 const 重载(或者实际上是从该重载实例化的标准库深处的某些东西)。
我的问题是是否可以安全地忽略该警告。
在我看来,std::shared_ptr<Bar> 的两个成员函数在getBar() const 中被调用:转换构造函数和析构函数。
// converting constructor
template <class Y>
std::shared_ptr<const Bar>::shared_ptr(std::shared_ptr<Y> &&r)
这用于从getBar()的返回值初始化getBar() const的返回值。这没有列出任何需要Y(在我的情况下为Bar)才能完成的先决条件(C++11 27.2.2.1 §20-22)。
// destructor
std::shared_ptr<const Bar>::~shared_ptr()
27.2.2.2 §1 规定当被销毁的共享指针为空时,没有副作用。
我理解为什么我会收到警告 - 析构函数代码还必须注意必须在存储的指针上调用 delete 的情况,并且此代码确实会删除不完整的类型。但在我看来,在我的情况下永远无法达到,所以getBar() const 是安全的。
我是正确的,还是我忽略了一个电话或其他可能使getBar() const 实际上删除不完整类型的东西?
【问题讨论】:
-
const_cast<Foo*>(this)->getBar();是 BAD 把戏 - 你最好从非常量版本调用 const 版本。 -
@ikh 我永远无法理解这个论点。就我而言,如果非常量版本修改了
*this,那么你就完蛋了。在您的情况下,如果 const 版本返回一个指向 实际声明const的指针,那么您就完蛋了。两者都有一个失败点,你只需要一个额外的演员。 -
在 const-calls-non-const 中,由类的用户确保不会在 const 对象上调用 const 版本。在非 const-calls-const 中,由类的创建者来确保逻辑有效。不要让你的课程成为没有检查你的逻辑的用户的炸弹。
-
@NeilKirk 我不认为它会给用户带来负担,它只是要求类的实现者不要在非常量重载中修改
*this。 -
如果它不修改
*this,那么函数应该是const。哎呀,现在你有两个 const 函数了!
标签: c++ c++11 shared-ptr incomplete-type