未实例化方法的默认空用法 class

Default empty usage of methods of uninstantiated class

在我的系统中,我有许多回调,其中包含调用 classes 的方法,这些回调未根据某些配置值实例化,当它们未初始化时,我希望调用它们时不执行任何操作,而不是引发段错误。 例如我有一些 InitManager class 在它的构造函数中我们有:

if (config.is_connected) { std::shared<CloudClient> cloud_client = std::make_shared<CLoudCLient>(); }

并且在 InitManager 中我有一个来自另一个进程的一些事件的回调,其中包括以下内容:

...
cloud_client->saveData();
...
cloud_client->notifyUser();
...

所以我目前的解决方案是在使用每种方法之前:

...
if (cloud_client) {
    cloud_client->saveData();
}
...
if (cloud_client) {
   cloud_client->notifyUser();
}
...

它保留了我想要的行为。问题是,每当另一个开发人员添加新方法或使用旧方法时,他可能不会检查 cloud_client 是否存在,而我们只能在检查该特定配置时通过测试来弄清楚。此外,我的解决方案使代码更难阅读,因为它包含许多 if 条件。 如果有人有一些设计解决方案可以让我做到:

cloud_client->notifyUser(); 

每次都没有if条件,当云客户端不存在时什么也不做。如果开发人员没有使用

,甚至只是使每个 class 方法的使用都在编译中失败
 `if (cloud_client)`

会很棒的!

谢谢你,OP,编辑你的问题。你做的很好,问题已经清楚了。

我建议 'wrapper' class 用于 CloudClient - 我们称它为 CloudClientWrapper,它包含指向 CloudClient 实例的指针(可能be nullptr) 作为成员变量。 CloudClientWrapper 然后可以负责测试那个变量是否是 nullptr,这意味着调用者不需要担心它。

为了防止外部代码直接调用 CloudClient 方法,声明它们 private 并使 CloudClientWrapper 成为 CloudClientfriend

所以,像这样:

class CloudClient
{
friend class CloudClientWrapper;

private:
    void Foo ();
    void Bar ();
    // ...
};

class CloudClientWrapper
{
public:
    CloudClientWrapper (CloudClient *client) : m_client (client) { }
    
    void Foo () { if (m_client) m_client->Foo (); }
    void Bar () { if (m_client) m_client->Bar (); }
    // ....
    
private:
    CloudClient *m_client;
};

当然,您的方法可以采用参数并具有 return 类型。 CouldClientWrapper 只需要传递它们。可能有很多样板文件,但我没有找到更好的方法。

顺便说一下,完全在头文件中实现 CloudClientWrapper 可能会有一些性能优势。它使编译器可以轻松地内联代码。有 link 时间优化 (LTO) 这样的东西,它旨在做同样的事情,但根据我的经验,它会减慢 link 时间并生成一堆巨大的中间构建产品(我已经放弃了)。