我在c ++中搜索扩展方法的实现,并且在这个comp.std.c ++讨论中提到了polymorphic_map
可以用于与类关联的方法,但是,提供的链接似乎已经死了.有没有人知道答案所指的是什么,或者是否有另一种方法以类似的方式扩展类到扩展方法(可能通过一些mixins的使用?).
我知道规范的C++解决方案是使用自由函数; 这更多是出于好奇而不是其他任何事情.
Dav*_*eas 68
不同语言以不同方式处理发展.特别是对于OO而言,C#和Java有一个强烈的观点,导致一切都是一个对象心态(C#在这里稍微宽松一点).在该方法中,扩展方法提供了一种扩展现有对象或接口以添加新功能的简单方法.
C++中没有扩展方法,也不需要它们.在开发C++时,忘记一切都是对象范例 - 顺便说一下,即使在Java/C#[*]中也是如此.在C++中采用了不同的思维方式,有对象,并且对象具有本身就是对象的一部分的操作,但是还有其他操作构成了接口的一部分,不需要成为类的一部分.Herb Sutter必须阅读的内容是什么?,作者辩护(并且我同意)您可以使用简单的自由函数轻松扩展任何给定的类.
作为一个特别简单的示例,标准模板化类basic_ostream
具有一些成员方法来转储某些基本类型的内容,然后通过使用现有公共接口将该功能扩展到其他类型的(也是模板化的)自由函数进行增强.例如,std::cout << 1;
实现为成员函数,std::cout << "Hi";
而是根据其他更基本的成员实现的自由函数.
C++中的可扩展性是通过自由函数实现的,而不是通过向现有对象添加新方法的方式实现的.
[*]一切都不是对象.
在给定的域中,将包含一组可以建模的实际对象以及可以应用于它们的操作,在某些情况下,这些操作将是对象的一部分,但在某些其他情况下它们不会.特别是你会发现语言中的实用程序类声称一切都是对象,而那些实用程序类只不过是一个试图掩盖这些方法不属于任何特定对象的事实的层.
甚至一些作为成员函数实现的操作也不是对象的真正操作.考虑添加一个Complex
数字类,第一个参数的操作sum
(或+
)多于第二个参数?为什么a.sum(b);
或b.sum(a)
不应该sum( a, b )
?
强制操作成为成员方法实际上产生了奇怪的效果 - 但我们只是习惯了它们:即使实现完全对称a.equals(b);
,b.equals(a);
也可能有完全不同的结果equals
.(考虑当其中一个a
或是b
空指针时会发生什么)
Aki*_*shi 24
Boost Range Library的方法使用operator |().
r | filtered(p);
Run Code Online (Sandbox Code Playgroud)
我也可以用同样的方式为字符串编写trim.
#include <string>
namespace string_extension {
struct trim_t {
std::string operator()(const std::string& s) const
{
...
return s;
}
};
const trim_t trim = {};
std::string operator|(const std::string& s, trim_t f)
{
return f(s);
}
} // namespace string_extension
int main()
{
const std::string s = " abc ";
const std::string result = s | string_extension::trim;
}
Run Code Online (Sandbox Code Playgroud)
简短的回答是你不能这样做.答案很长,你可以模拟它,但要注意你必须创建大量的代码作为解决方法(实际上,我认为没有一个优雅的解决方案).
在讨论中,使用operator-提供了一个非常复杂的解决方法(在我看来这是个坏主意).我想死链接中提供的解决方案更不相似(因为它基于运算符|).
这基于能够与运算符的扩展方法做或多或少相同的能力.例如,如果你想为你的新类Foo重载ostream的operator <<,你可以这样做:
class Foo {
friend ostream &operator<<(ostream &o, const Foo &foo);
// more things...
};
ostream &operator<<(ostream &o, const Foo &foo)
{
// write foo's info to o
}
Run Code Online (Sandbox Code Playgroud)
正如我所说,这是C++中唯一可用于扩展方法的类似机制.如果您可以自然地将您的函数转换为重载运算符,那么它很好.唯一的另一种可能性是人为地超载与您的目标无关的运算符,但这会让您编写非常混乱的代码.
我能想到的最相似的方法是创建一个扩展类并在那里创建新方法.不幸的是,这意味着你需要"适应"你的对象:
class stringext {
public:
stringext(std::string &s) : str( &s )
{}
string trim()
{ ...; return *str; }
private:
string * str;
};
Run Code Online (Sandbox Code Playgroud)
然后,当你想做那些事情时:
void fie(string &str)
{
// ...
cout << stringext( str ).trim() << endl;
}
Run Code Online (Sandbox Code Playgroud)
如上所述,这并不完美,我认为不存在那种完美的解决方案.抱歉.
这是我在C++中看到的最接近扩展方法的东西.我个人喜欢它的使用方式,也许这就是我们最接近这种语言的扩展方法.但是有一些缺点:
一个办法:
#include <iostream>
using namespace std;
class regular_class {
public:
void simple_method(void) const {
cout << "simple_method called." << endl;
}
};
class ext_method {
private:
// arguments of the extension method
int x_;
public:
// arguments get initialized here
ext_method(int x) : x_(x) {
}
// just a dummy overload to return a reference to itself
ext_method& operator-(void) {
return *this;
}
// extension method body is implemented here. The return type of this op. overload
// should be the return type of the extension method
friend const regular_class& operator<(const regular_class& obj, const ext_method& mthd) {
cout << "Extension method called with: " << mthd.x_ << " on " << &obj << endl;
return obj;
}
};
int main()
{
regular_class obj;
cout << "regular_class object at: " << &obj << endl;
obj.simple_method();
obj<-ext_method(3)<-ext_method(8);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这不是我的个人发明,最近我的一个朋友把它寄给了我,他说他是从大学邮件列表中得到的.
归档时间: |
|
查看次数: |
23034 次 |
最近记录: |