我有一个接口类和一个可能是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
解决方案 优选的)?
还有更好的方法吗?
答案 0 :(得分:18)
不要与语言作斗争:
if (ptr) ptr->SomeMethod();
非常清晰,可读,并且比难以调试的宏替代或花哨的包装类具有更少的字符。关于ptr
可能被评估两次的事实也是明确的。
C ++(还没有)“只有非空运算符才调用”cf. C#
答案 1 :(得分:9)
避免使用宏,你可以这样做:
//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足够清楚,会给你更明确的错误。
答案 2 :(得分:1)
好吧,你总是可以为你编写一个包装类来检查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();