开发者

Choosing between instance methods and free functions?

Adding functionality to a class can be done by adding a method or by defining a function that takes an object as its first parameter. Most programmers that I know would choose for the solution of adding an instance method.

However, I sometimes prefer to create a separate function. For example, in the example code below Area and Diagonal are defined as f开发者_Python百科ree functions instead of methods. I find it better this way because I think these functions provide enhancements rather than core functionality.

Is this considered a good/bad practice? If the answer is "it depends", then what are the rules for deciding between adding method or defining a separate function?

class Rect
{
public:
    Rect(int x, int y, int w, int h) :
        mX(x), mY(y), mWidth(w), mHeight(h)
    {
    }

    int x() const { return mX; }

    int y() const { return mY; }

    int width() const { return mWidth; }

    int height() const { return mHeight; }

private:
    int mX, mY, mWidth, mHeight;
};


int Area(const Rect & inRect)
{
    return inRect.width() * inRect.height();
}


float Diagonal(const Rect & inRect)
{
    return std::sqrt(std::pow(static_cast<float>(inRect.width()), 2) + std::pow(static_cast<float>(inRect.height()), 2));
}


GoTW #84 explored this question with respect to std::string. He tended toward rather the opposite idea: most functions should be global unless they really need to be members.

I'd say most modern C++ tends toward the same idea. If you look through Boost, for example, quite a bit is done with free functions.


If you want to use it with other, unrelated classes, it should be a free function with overrides.

For example, you could override float Area( Hexagon const & ) and float Diagonal( Hexagon const & ). x, y, width, and height however mean different things for different shapes.

Abstract base classes (or unrelated homonym methods) are another solution, but free functions are user-extensible so users effectively get a more uniform interface once they've added their own stuff.

Avoid free functions with ambiguous names, so that unrelated functions don't become "competing" overrides.


I'd say that it depends on what your goals are. If the function is a member function, then you can use . and -> notation with it, and it's better integrated with the class. It also allows for polymorphism. If you want your function to be virtual, it needs to be a member function.

However, there is a school of thought that it's better encapsulation to make functions member functions only if they need to be. So, if the function doesn't actually need access to member variables (presumably because it can do what it needs to do with just the public functions), then you make it a separate function which is not a member of the class. That way it can't mess with the internals even by accident.

One other consideration is that if it's not a member function, you have to worry about whether other types can or should be cast to the type that is now the first parameter to the function. Sometimes that's desirable and sometimes not. If it's a member function, then that's not a problem (or an opportunity, depending on what you're trying to do).

Personally, I don't like functions which are separate from the class, but you're often forced to write functions that way when you don't have control over the class, or you can't change it for compatability reasons or whatnot.

Really, I think that it comes down to what's most important to you, and what you're really trying to do. I think that having the function be a part of the class makes it easier to use and more object-oriented, but it's better encpasulation if you restrict how much has access to the private members of your class.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜