简体   繁体   English

有没有办法使成员函数不能从构造函数调用?

[英]Is there a way to make member function NOT callable from constructor?

I have member function (method) which uses 我有使用的成员函数(方法)

std::enable_shared_from_this::weak_from_this() 

In short: weak_from_this returns weak_ptr to this . 简而言之: weak_from_thisweak_ptr返回给 One caveat is it can't be used from constructor. 一个警告是它不能从构造函数中使用。 If somebody would use my function from constructor of inherited class, weak_from_this inside it would return expired weak_ptr . 如果有人会从继承类的构造函数中使用我的函数, weak_from_this里面会返回过期的weak_ptr I guard against that with assertion checking that it's not expired, but it's a run-time check. 我通过断言检查它没有过期来防止这种情况,但这是一次运行时检查。

Is there a way to check against it at compile time? 有没有办法在编译时检查它?

I am afraid the answer is "no, it's not possible to protect against this at compile-time." 我担心答案是“不,在编译时不可能防止这种情况发生。” It's always difficult to prove a negative, but consider this: if it was possible to protect a function this way, it would probably have been done for weak_from_this and shared_from_this in the standard library itself. 它总是很难证明一个消极的,但想想看:如果有可能保护功能这样的话,大概已经为做weak_from_thisshared_from_this标准库本身。

No there is no way. 不,没有办法。 Consider: 考虑:

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
}

The thing is there is a reason you want to check for not calling shared_from_this in the constructor. 问题是你有理由检查是否在构造函数中调用了shared_from_this Think about that reason. 想想那个理由。 It's not that shared_from_this cannot be called, it's because it's return value has no way of being assigned yet. 这不是shared_from_this不能被调用,这是因为它的返回值无法分配。 It is also not because it will never be assigned. 这也不是因为它永远不会被分配。 It's because it will be assigned later in the execution of the code. 这是因为它将在稍后的代码执行中分配。 Order of operation is a runtime property of your program. 操作顺序是程序的运行时属性。 You cannot assert at compile time for order of operation, which is done at runtime. 您无法在编译时断言操作顺序,这是在运行时完成的。

Not as such, but - if performance is not an issue, you could add a flag which indicates construction is complete, and use that to fail at run-time with such calls: 不是这样,但是 - 如果性能不是问题,您可以添加一个表示构造已完成的标志,并在运行时使用该标志进行此类调用:

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 };
}

You could also make these checks only apply when compiling in DEBUG mode (eg with conditional compilation using the preprocessor - #ifndef NDEBUG ) so that at run time you won't get the performance penalty. 您还可以使这些检查仅在DEBUG模式下编译时适用(例如,使用预处理器进行条件编译 - #ifndef NDEBUG ),这样在运行时您将不会受到性能损失。 Mind the noexcept s though. 但请注意noexcept

An alternative to throwing could be assert() 'ing. 抛出的替代方法可以是assert()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM