C++类扩展

pau*_*ons 8 c++ extension-methods class

有没有办法向类添加新方法,而不修改原始类定义(即包含类和相应的.h文件的编译.lib),如C#的类扩展方法?

Kri*_*son 17

没有.C++没有这样的能力.

正如其他答案中所提到的,常见的解决方法是:

  • 定义派生类,可能使用工厂来隐藏实际的实现类
  • 定义装饰器
  • 定义对该类实例进行操作的非成员函数


Gle*_*len 11

不,你不能用C++做到这一点.

如果你想要达到这样的目的,你有两个选择,

  • 您可以继承自该类(如果这是一个选项,它可能不合法,因为该类可能尚未编写为允许继承)
  • 您可以编写自己的包装类,它具有相同的接口+新方法,并委托给您要扩展的那个.

我更喜欢代表团的做法.

  • +1"赞成合成而不是继承" (4认同)
  • @mh,可能不是。但是现在他们知道要放入SO或Google搜索中的正确术语 (2认同)

Pon*_*gge 5

C#类扩展方法主要是语法糖.您可以使用自由函数获得相同的功能(即,具有对类的引用或常量引用的函数作为其第一个参数).既然这对STL很有效,为什么不为你的班级?


Pau*_* II 5

在 C++ 中,您可以使用自由函数,但有时,当您将许多函数嵌套在一起时,扩展方法会更有效。看一下这段 C# 代码:

var r = numbers.Where(x => x > 2).Select(x => x * x);
Run Code Online (Sandbox Code Playgroud)

如果我们使用 free 函数在 C++ 中编写它,它将如下所示:

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

这不仅很难读,而且很难写。解决这个问题的常见方法是创建所谓的 pipable 函数。这些函数是通过重载|管道运算符(实际上是或运算符)创建的。所以上面的代码可以这样写:

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

这更容易阅读和编写。许多库使用 pipable 函数来表示范围,但它也可以扩展到其他类。Boost 在他们的range库中使用它,pstade oven使用它,这个 C++ linq库也使用它。

如果您想编写自己的 pipable 函数,请在此处boost 解释如何执行此操作。然而,其他库提供了函数适配器以使其更容易。Pstade Egg 有一个pipable 适配器,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); };
};
Run Code Online (Sandbox Code Playgroud)

然后使用静态初始化来初始化该函数,如下所示:

range_extension<contains_t> contains = {};
Run Code Online (Sandbox Code Playgroud)

然后你可以像这样使用你的 pipable 函数:

if (numbers | contains(5)) printf("We have a 5");
Run Code Online (Sandbox Code Playgroud)