开发者

In C or C++, is there a way to extend a class without inheritance?

Is there a way to implement functionality like Class Categories (of Objec开发者_运维百科tive-C) or Extension Methods (of C# 3.0) in C and/or C++?


C++ has free functions, but sometimes extension methods work better when you nest many functions together. Take a look at this C# code:

var r = numbers.Where(x => x > 2).Select(x => x * x);

If we write this in C++ using free function it would look like this:

auto r = select(where(numbers, [](int x) { return x > 2; }), [](int x) { return x * x; });

Not only is this difficult to read, but it is difficult to write. The common way to solve this is to create what is called a pipable function. These functions are created by overloading the | pipe operator(which is just really the or operator). So the code above could be written like this:

auto r = numbers | where([](int x) { return x > 2; }) | select([](int x) { return x * x; });

Which is much easier to read and write. Many libraries use pipable function for ranges, but it could be expanded to other classes as well. Boost uses it in their range library, pstade oven uses it, and also this C++ linq library uses it as well.

If you would like to write your own pipable function, boost explain how to do that here. Other libraries, however, provide function adaptors to make it easier. Pstade egg has a pipable adaptor, and linq provides the range_extension adaptor to create a pipable function for ranges as least.

Using linq, you first just create your function as a function object like this:

struct contains_t
{
    template<class Range, class T>
    bool operator()(Range && r, T && x) const
    { return (r | linq::find(x)) != boost::end(r); };
};

Then you initialize the function using static initialization like this:

range_extension<contains_t> contains = {};

Then you can use your pipable function like this:

if (numbers | contains(5)) printf("We have a 5");


Not really. It's not the C++ way to treat classes like this.

Amongst others, Meyers argue that it's best to have a small class with the minimal set of operations that make it fully useful. If you want to expand the feature set, you may add an utility namespace (e.g. namespace ClassUtil) that contains non-member utility functions that operate on that minimal class. It's easy to add functions to a namespace from anywhere.

You can check a discussion on the subject here.


C++ doesn't have sealed classes or single class inheritance, so in most cases you can subclass the base class. There are creative ways to make a class non-inheritable, but they are few and far in between. In general, C++ doesn't have the problems C# does that gave birth to extension methods.

C is not Object Orientated, so the question doesn't really apply.


With regard to C#'s extension methods: Not directly. C++ has less need for these things because C++ supports free functions. I've never used Objective-C so I can't comment there.


Can you use an interface? Extension methods are an easy way to avoid subclassing, but they are rendered semi-useless when proper OO techniques are used. The reason that they are used with Linq so much is so that the VS team did not have to go and update code that would most likely break a lot of legacy applications.

Per MSDN: "In general, we recommend that you implement extension methods sparingly and only when you have to. Whenever possible, client code that must extend an existing type should do so by creating a new type derived from the existing type."

http://msdn.microsoft.com/en-us/library/bb383977.aspx

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜