如果没有调用某个函数,则禁止编译代码

时间:2016-02-23 21:33:09

标签: c++ templates c++11 metaprogramming

如果没有调用特定的函数,C ++中是否有一种禁止编译代码的方法。

想象一下,我有一些课程:

class CExample
{
public:
    void Init();
    void DoWork();

};

如果没有为类对象调用 Init()函数,是否有办法禁止调用 DoWork()

我想禁止写这样的代码:

CExample e;
e.DoWork();

并允许此版本:

CExample e;
e.Init();
e.DoWork();

我可以通过元编程以某种方式达到这种行为吗?

5 个答案:

答案 0 :(得分:12)

您可以使用构造函数而不是Init

在他的notes about exception safety in the standard library, as appendix to the 3rd edition of The C++ Programming Language中,Bjarne Stroustrup讨论了如何使用init函数与类不变量的概念不一致。它通常是Bad Practice™,主要是出于这个原因。

一些旧的GUI框架(如Microsoft的MFC)使用init函数来执行派生类特定的初始化。有other techniques to do that,仅包括passing the required information up the construction chain个参数。

答案 1 :(得分:4)

不,那将是糟糕的设计。如果必须调用它才能使对象可用,则应在构造函数中调用它。在构造一个对象之后,所有公共方法都应该是可调用的 - 该对象应该是完全构造的并且可以使用。

答案 2 :(得分:1)

在编译时,不知道Init()之前是否已调用DoWork()。这只能在运行时决定。因此元编程在这里没用。

答案 3 :(得分:1)

您应该将init代码放入构造函数中以强制正确构造类。但是,如果您真的坚持,并且您的init函数确实不是多态的,那么您可以将CRTP与受保护的构造函数一起使用:

template <typename What>
class InitMe : public What
{
public:
    InitMe() : What() { this->Init(); }
};

class CExample
{
public:
    void Init() {}
    void DoWork() {}

protected:
    CExample() {}
};


int main()
{
    //CExample e;  // Error: protected constructor.

    InitMe<CExample> e;
    e.DoWork();
}

答案 4 :(得分:1)

由于Cheers and hth. -AlfRob K都已触及,您绝对希望在类构造函数中执行init工作。必须调用一个单独的函数来确保你的课程准备就绪是一个糟糕的设计。

然而,话虽如此,你可以检测,如果它已被调用并采取相应行动:

void CExample::Init()
{
    // things
    ...
    init = true;
}

void CExample::DoWork()
{
    if (!init)
    {
        Init();
    }
}