我有使用的成员函数(方法)
std::enable_shared_from_this::weak_from_this()
简而言之:weak_from_this
将weak_ptr
归还给了他。一个警告是它不能从构造函数中使用。如果有人会从继承类的构造函数中使用我的函数,那么weak_from_this
会返回过期的weak_ptr
。我通过断言检查它没有过期来防止这种情况,但这是一次运行时检查。
有没有办法在编译时检查它?
我担心答案是“不,在编译时不可能防止这种情况发生。”总是很难证明是消极的,但要考虑到这一点:如果以这种方式保护函数是可能的,那么标准库本身可能已经为weak_from_this
和shared_from_this
做了。
不,没有办法。考虑:
void call_me(struct widget*);
struct widget : std::enable_shared_from_this<widget> {
widget() {
call_me(this);
}
void display() {
shared_from_this();
}
};
// later:
void call_me(widget* w) {
w->display(); // crash
}
问题是你有理由检查是否在构造函数中调用shared_from_this
。想想那个理由。并不是说shared_from_this
不能被调用,这是因为它的返回值无法被分配。这也不是因为它永远不会被分配。这是因为它将在稍后的代码执行中分配。操作顺序是程序的运行时属性。您无法在编译时断言操作顺序,这是在运行时完成的。
不是这样,但是 - 如果性能不是问题,您可以添加一个表示构造已完成的标志,并在运行时使用该标志进行此类调用:
class A {
// ... whatever ...
public:
A() {
// do construction work
constructed = true;
}
foo() {
if (not constructed) {
throw std::logic_error("Cannot call foo() during construction");
}
// the rest of foo
}
protected:
bool constructed { false };
}
您还可以使这些检查仅在DEBUG模式下编译时适用(例如,使用预处理器进行条件编译 - #ifndef NDEBUG
),这样在运行时您将不会受到性能损失。但请注意noexcept
s。
投掷的另一种选择可能是assert()
'ing。