有没有一种方法来添加新的方法到类,而不需要修改原来的类定义(即编译的.lib包含类和相应的.h文件)一样的C#类的扩展方法?
Answer 1:
号C ++有没有这样的能力。
正如在其他的答案中提到,常见的解决方法是:
- 定义一个派生类,或许还有一个工厂隐藏实际的实现类
- 定义装饰类
- 限定在类的实例操作非成员函数
Answer 2:
不,你不能在C ++中做到这一点。
如果你想实现这样的事情,你有2种选择,
- 你可以从你的类继承的(如果这是一种选择,它可能不是合法的,因为该类可能没有被写入允许继承)
- 您可以编写具有相同的接口+你的新方法,并委托要扩展一个自己的包装类。
我更喜欢代表团的做法。
Answer 3:
C#类的扩展方法大多是语法糖。 你得到了免费的功能(即功能与作为其第一个参数的引用或常量引用您的类)相同的功能。 由于这非常适用于STL的,为什么不为你的类?
Answer 4:
在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功能,但它可以扩展到其他类为好。 升压用它在其范围内的库,pstade 烘箱使用它,这也C ++ LINQ库使用它。
如果你想编写自己的pipable功能,提高讲解如何做到这一点在这里 。 其他图书馆,然而,提供的功能适配器,使其更容易。 Pstade鸡蛋有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); };
};
然后你使用静态初始化这样的初始化函数:
range_extension<contains_t> contains = {};
然后你可以使用你的pipable功能如下:
if (numbers | contains(5)) printf("We have a 5");
Answer 5:
一般不会。 但是,如果库不创建需要您的扩展类的实例,你可以修改创建类的实例,并需要您的扩展在应用中的所有地方,有一种方法可以去:
- 创建被称为在需要的类的实例,并返回一个指向实例的所有地方工厂函数(谷歌的设计模式厂 ,...)。
- 创建你想要的扩展派生类。
- 使工厂函数返回你的派生类代替原来的类。
例:
class derivedClass: public originalClass { /* ... */};
originalClass* createOriginalClassInstance()
{
return new derivedClass();
}
- 当你需要访问的扩展,需要到原班人马强制转换为派生类,当然。
这大致是如何实现由格伦提出的“继承”方法。 格伦的方法“有相同的接口包装类”也是从理论的角度来看很不错,但略有不同的特性,使得它不太可能在你的情况下工作。
Answer 6:
有其中这是可以做到的一种方式。 这就是通过放松你的要求一点。 在C ++中,人们常常说,一个类的接口由不仅仅是它的成员函数,但是,关于类工作的所有功能 。
也就是说,它可以给出的类作为参数非成员函数,应考虑它的接口的一部分。
例如, std::find()
或std::sort()
是接口的一部分std::vector
,即使他们不是类的成员。
如果你接受这个定义,那么你可以随时通过简单地添加非成员函数扩展一个类。
Answer 7:
你不能添加物理方法或数据的类文件,该文件是二进制形式。 但是,您可以通过编写扩展类添加到类的对象的方法和数据(功能和状态)。 这是不是直线前进,需要元对象协议和接口的编程基础。 你需要做很多C ++实现这一目标,因为它不支持反射开箱。 在当您查询通过原有的类对象的指针由您的新扩展类实现的接口这样的实现,元对象实现通过返回的元类对象,它在运行时创建扩展类接口指针。 这是许多定制的(基于插件的)软件应用框架是如何工作的。 但是,你必须记住,它需要许多其他MOP机制写入实例化,使用其中的对象关系描述字典中的所有类元对象,并给原始和扩展类对象的正确接口指针。 达索系统的CATIA V5是用这种所谓的CAA V5架构,您可以通过所需的功能编写新的扩展类扩展现有的组件。
Answer 8:
抱歉,没有。 一旦你的代码是在OBJ,你不能改变它。 如果这可以在VC部分类来实现将已经支持。 有一个例外,虽然,操作方法可以使用全局函数,漂亮怎么样的cout <<在STL实现扩展。
Answer 9:
你当然可以:
template <typename Ext>
class Class: public Ext { /* ... */ };
这并不意味着它虽然最好的办法。