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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了有没有办法使成员函数不能从构造函数调用?相关的知识,希望对你有一定的参考价值。

我有使用的成员函数(方法)

std::enable_shared_from_this::weak_from_this() 

简而言之:weak_from_thisweak_ptr归还给了他。一个警告是它不能从构造函数中使用。如果有人会从继承类的构造函数中使用我的函数,那么weak_from_this会返回过期的weak_ptr。我通过断言检查它没有过期来防止这种情况,但这是一次运行时检查。

有没有办法在编译时检查它?

答案

我担心答案是“不,在编译时不可能防止这种情况发生。”总是很难证明是消极的,但要考虑到这一点:如果以这种方式保护函数是可能的,那么标准库本身可能已经为weak_from_thisshared_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),这样在运行时您将不会受到性能损失。但请注意noexcepts。

投掷的另一种选择可能是assert()'ing。

以上是关于有没有办法使成员函数不能从构造函数调用?的主要内容,如果未能解决你的问题,请参考以下文章

static成员函数不能调用non-static成员函数

C++调用父类的构造函数规则

子父类中的构造函数

C++的构造函数为何不能为虚函数

c++,类的对象作为形参时一定会调用复制构造函数吗?

何时子类必须显示调用父类带参构造函数