在c ++中是否有以下内容:
https://kotlinlang.org/docs/reference/null-safety.html#safe-calls
我想缩短如下调用:
int x = 0;
IPtr pClass(...);
if (pClass)
{
pClass->...
pClass->...
x = pClass->function();
}
我可以使用任何宏/语言技巧使其看起来像伪代码?
IPtr pClass(...);
pClass?->... // only call function if pClass != nil
pClass?->... // only call function if pClass != nil
int x = pClass?->function() | 0; // only call function if pClass != nil, otherwise assign 0 to x
编辑 - 使用帐户
我为另一个软件开发了一些插件,我自己也可以使用其他插件。
最简单的例子是一个日志插件,我想在我的代码中遍布很多日志调用,并且只想记录某些内容,如果日志模块已加载并且可用。我从我的插件所用的软件中获得了指向单例记录器模块的指针。我的代码会受到以下日志行的污染:
if (logger)
{
logger->log(...);
}
如果没有安全的话,那么将它作为一个单独的衬垫会更美观和紧凑......
答案 0 :(得分:3)
代码样式解决方案( RIGHT 解决方案)
可以改进设计以解决此问题。如果未加载logger
插件,则不应该收到nullptr
,而应该是一个虚拟logger
对象,其实现为空。
工厂(尤其是创建全局基础架构对象的工厂)不应返回nullptr
。
智能指针包装
这是您可以使用的概念:
struct Object {
void run() { std::cout << "run" << std::endl; }
void stop() { std::cout << "stop" << std::endl; }
};
template < typename T >
struct safe_ptr : std::unique_ptr<T> {
safe_ptr(T * ptr) : std::unique_ptr<T>(ptr ? ptr : &t) {}
virtual ~safe_ptr() {
if (::std::unique_ptr<T>::get() == &t)
::std::unique_ptr<T>::release();
}
using std::unique_ptr<T>::operator*;
using std::unique_ptr<T>::operator->;
private:
T t;
};
int main() {
safe_ptr<Object> safe(nullptr);
safe->run();
}
如果使用safe_ptr<T>
初始化,nullptr
将使用指向对象的有效指针。
您当然可以改进此解决方案,使其仅适用于定义默认回退静态对象的对象,例如:
struct Object {
void run() { std::cout << "run" << std::endl; }
void stop() { std::cout << "stop" << std::endl; }
static Object fallback;
};
Object Object::fallback;
template < typename T >
struct safe_ptr : std::unique_ptr<T> {
safe_ptr(T * ptr) : std::unique_ptr<T>(ptr ? ptr : &T::fallback) {}
virtual ~safe_ptr() {
if (::std::unique_ptr<T>::get() == &T::fallback)
::std::unique_ptr<T>::release();
}
using std::unique_ptr<T>::operator*;
using std::unique_ptr<T>::operator->;
};
这将避免私有T t
的多次分配,并允许fallback
对象的特定初始化。
答案 1 :(得分:2)
不是你建议的解决方案,但由于我个人觉得这些“安全”的呼叫操作员特别难以理解,我建议基于现场调用的lambda替代代码风格:
int const x = [&] {
IPtr const pClass = /*...*/;
if(!pClass)
return 0;
pClass->/*...*/;
pClass->/*...*/;
return pClass->function();
}();
这个Gizmo被Javascipt人称为IIFE,用分支代码路径包装复杂的初始化非常有用。