仅当指针不是 nullptr 时才调用方法

Call method only if pointer is not nullptr

本文关键字:调用 方法 nullptr 指针      更新时间:2023-10-16

我有一个接口类和一个指针,可能nullptr,如果是,我只是跳过方法调用:

if (ptr != nullptr)
{
ptr->SomeMethod();
}
...
if (ptr != nullptr)
{
ptr->SomeOtherMethod();
}
...
if (ptr != nullptr)
{
ptr->SomeMethodThatWasntMentionedBefore();
}

更新:以下不太正确:

我可以使用以下宏提高此代码的可读性:

#define CALL_IF_NOT_NULLPTR(ptr, method_call) if (ptr != nullptr) { ptr->method_call; };
CALL_IF_NOT_NULLPTR(ptr, SomeMethod());
CALL_IF_NOT_NULLPTR(ptr, SomeOtherMethod());
CALL_IF_NOT_NULLPTR(ptr, SomeMethodThatWasntMentionedBefore());

有没有办法在没有宏的情况下做同样的事情(C++11解决方案是 首选(?

有没有更好的方法?

不要与语言作斗争:

if (ptr) ptr->SomeMethod();

非常清晰、可读,并且比难以调试的宏替代或花哨的包装器类具有更少的字符。它还明确指出ptr可能会被评估两次。

C++(尚(没有"仅在非空运算符时才调用"参见 C#

避免使用宏,你可以这样做:

//Lambda call
template<typename T, typename F, typename... Args>
void call_if_not_nullptr(T* ptr, F&& function, Args&&... args)
{
if(ptr != nullptr)
std::forward<F>(function)(std::forward<Args>(args)...);
}
//Member function call
template<typename T, typename R, typename... Args>
void call_if_not_nullptr(T* ptr, R(T::*mem_fun)(Args...), Args&&... args)
{
if(ptr != nullptr)
(ptr.*memfun)(std::forward<Args>(args)...);
}

用法:

class SomeType
{
public:
void noArgsFunction();
void argsFunction(int, int);
}
SomeType* pointer = new SomeType();
//Member function call
call_if_not_nullptr(pointer, &SomeType::noArgsFunction);
//Member function call with arguments
call_if_not_nullptr(pointer, &SomeType::argsFunction, 0, 3);
//Lambda call
call_if_not_nullptr(pointer, [pointer](){ pointer->noArgsFunction(); });
//Lambda call with arguments
call_if_not_nullptr(pointer, [pointer](int a, int b){ pointer->argsFunction(); }, 0, 5);

但是,我不建议这样做,检查nullptr足够清楚,并且会给您更清晰的错误。

好吧,您可以随时为您编写一个检查nullptr的包装类:

class
t_Wrapper
{
private: t_Target * m_ptr;
...
public: void
SomeMethod()
{
if(m_ptr)
{
m_ptr->SomeMethod();
}
}
public: void
SomeOtherMethod()
{
if(m_ptr)
{
m_ptr->SomeOtherMethod();
}
}
...
public: void
SomeMethodThatWasntMentionedBefore()
{
if(m_ptr)
{
m_ptr->SomeMethodThatWasntMentionedBefore();
}
}
};
t_Wrapper wrap(ptr);
wrap.SomeMethod();
wrap.SomeOtherMethod();
...
wrap.SomeMethodThatWasntMentionedBefore();