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

时间:2017-07-31 10:09:34

标签: c++ c++11

我有一个接口类和一个可能是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解决方案   优选的)?

还有更好的方法吗?

3 个答案:

答案 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();