如果未调用某些函数,则禁止编译代码

Forbid code to compile if some function is not called

本文关键字:禁止 编译 代码 函数 调用 如果      更新时间:2023-10-16

没有办法在C++中禁止代码编译,如果未调用特定函数。

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

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

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

我想禁止编写这样的代码:

CExample e;
e.DoWork();

并允许此版本:

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

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

你可以只使用构造函数而不是Init .

Bjarne Stroustrup 在标准库中关于异常安全的笔记中,作为第 3 版 The C++ Programming Language 的附录,讨论了使用 init 函数如何与类不变量的概念不一致。这通常是不良做法™,主要是出于这个原因。

一些旧的 GUI 框架(如 Microsoft 的 MFC)使用init函数来执行派生类特定的初始化。还有其他技术可以做到这一点,包括通过参数将所需的信息传递到构造链上。

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

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

您应该将 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();
}

正如 Cheers 和 hth. -Alf 和 Rob K 都提到的那样,你绝对希望在类构造函数中执行你的init工作。必须调用一个单独的函数来确保你的类正确准备就绪是糟糕的设计。

但是,话虽如此,您可以检测它是否已被调用并采取相应的行动:

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