Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is using non-member function a good practice?

Tags:

c++

c++11

Let's say I have a class where I have multiple functions with similar logic. Since I don't want to repeat myself, I extract the similar logic in a function. Is it good practice to have similarLogic as a non-member function if it does not use any class members? Or is there a better way to do this?

Please note that in my case, the similarLogic function is strictly specific to MyClass so it won't be used anywhere outside of it.

Example with a non-member function:

MyClass.h

class MyClass {
public:
    int func1();
    int func2();
};

MyClass.cpp

int similarLogic(int p_num){
    return 5 + p_num;
}

int MyClass::func1() {
    return similarLogic(1);
}

int MyClass::func2() {
    return similarLogic(2);
}
like image 273
Charles Marceau Avatar asked Dec 18 '22 15:12

Charles Marceau


2 Answers

Personally, I'd write similarLogic in an anonymous namespace within MyClass.cpp. In that way it's invisible outside that translation unit:

namespace {
    int similarLogic(int p_num){
        return 5 + p_num;
    }
}

Other approaches such as a private member of the class (static or otherwise) pollute the class definition. But that doesn't make the approach a poor choice. If the function requires class member data in the future, then refactoring is simpler than it would be with my favoured way.

Whatever you end up doing, polluting the global namespace is not desirable.

like image 78
Bathsheba Avatar answered Jan 10 '23 12:01

Bathsheba


If the functionality is only used by MyClass then the function should be a private member function.

If it does not use any MyClass attributes you can eventually make it static, but it's not necessary.

If it's similar logic that can be applied to different type, you can also use a template function. For instance :

// MyClass.h

class MyClass {
public:
    int func1();
    int func2();
private:
    template<class T> void similarLogic(T arg); 
};

template<class T> MyClass::similarLogic(T arg) {
    // Generic implementation
}
template<> MyClass::similarLogic<float >(float arg) {
    // Specialization for int
}

// MyClass.cpp
int MyClass::func1() {
    // Call generic implementation for int
    return similarLogic<int>(1);
}

int MyClass::func2() {
    // Call specialization for float
    return similarLogic<float>(2.34);
}
like image 22
Clonk Avatar answered Jan 10 '23 11:01

Clonk