有没有办法在C和/或C ++中实现类别(Objective-C)或扩展方法(C#3.0)等功能?
答案 0 :(得分:24)
C ++具有自由函数,但有时扩展方法在将多个函数嵌套在一起时效果更好。看看这个C#代码:
var r = numbers.Where(x => x > 2).Select(x => x * x);
如果我们使用自由函数在C ++中编写它,它将如下所示:
auto r = select(where(numbers, [](int x) { return x > 2; }), [](int x) { return x * x; });
这不仅难以阅读,而且难以编写。解决这个问题的常用方法是创建所谓的pipable函数。这些函数是通过重载|
管道运算符(它实际上是或运算符)来创建的。所以上面的代码可以这样写:
auto r = numbers | where([](int x) { return x > 2; }) | select([](int x) { return x * x; });
这更易于阅读和书写。许多库对范围使用pipable函数,但也可以扩展到其他类。 Boost在range库中使用它,pstade oven使用它,此C ++ linq库也使用它。
如果您想编写自己的pipable函数,请解释如何执行此操作here。但是,其他库提供了功能适配器以使其更容易。 Pstade egg有一个pipable adaptor,linq提供range_extension
适配器来为范围创建一个pipable函数。
使用linq,首先只需将函数创建为函数对象,如下所示:
struct contains_t
{
template<class Range, class T>
bool operator()(Range && r, T && x) const
{ return (r | linq::find(x)) != boost::end(r); };
};
然后使用静态初始化初始化函数,如下所示:
range_extension<contains_t> contains = {};
然后你可以像这样使用你的pipable函数:
if (numbers | contains(5)) printf("We have a 5");
答案 1 :(得分:4)
不是真的。处理这样的类并不是C ++方式。
除此之外,Meyers认为最好有一个小班级,其中最小的操作使其完全有用。如果要扩展功能集,可以添加包含在该最小类上运行的非成员实用程序功能的实用程序命名空间(例如,命名空间ClassUtil)。可以从任何地方轻松地向命名空间添加函数。
您可以查看有关主题here的讨论。
答案 2 :(得分:1)
C ++没有密封类或单个类继承,因此在大多数情况下,您可以继承基类。有一些创造性的方法可以使一个类不可继承,但它们很少,而且介于两者之间。一般来说,C ++没有产生扩展方法的问题。
C不是面向对象的,所以问题并不真正适用。
答案 3 :(得分:0)
关于C#的扩展方法:不直接。 C ++对这些东西的需求较少,因为C ++支持自由函数。我从未使用过Objective-C,所以我不能在那里发表评论。
答案 4 :(得分:0)
您可以使用界面吗?扩展方法是一种避免子类化的简单方法,但是当使用适当的OO技术时,它们会被渲染为半无用的。他们与Linq一起使用的原因是,VS团队不必去更新很可能会破坏许多遗留应用程序的代码。
每个MSDN: “一般情况下,我们建议您谨慎实施扩展方法,并且只在必要时才实现。只要有可能,必须扩展现有类型的客户端代码应该通过创建从现有类型派生的新类型来实现。”