移植Java代码到C++的技巧(整合)
作者:网络转载 发布时间:[ 2013/4/17 9:53:25 ] 推荐标签:
该类只有一个公有方法,即圆括号操作符重载函数,在C++中通常称这种类型的类为函数类。该方法的实现逻辑要求模参类型必须具备“小于”的可比较性,对于原始数据类型这是没有问题的,如int,short,float等。相比而言,对于自定义的类来说,则必须重载小于操作符。见如下C++代码:
using namespace std;
class MyTest
{
public:
MyTest(int value) {
_value = value;
}
~MyTest() {}
public:
bool operator< (const MyTest& o) const {
printf("operator < of MyTest is called here.
");
return _value - o._value < 0;
}
public:
int getValue() const {
return _value;
}
private:
int _value;
};
int main()
{
map<MyTest,int> m;
MyTest t5(5);
MyTest t2(2);
MyTest t10(10);
m.insert(make_pair(t5,5));
m.insert(make_pair(t2,2));
m.insert(make_pair(t10,10));
map<MyTest,int>::iterator it = m.begin();
printf("The count of the map is %d.
",m.size());
for (; it != m.end(); ++it)
printf("key = %d, value = %d
",(*it).first.getValue(),(*it).second);
return 0;
}
//operator < of MyTest is called here.
//operator < of MyTest is called here.
//operator < of MyTest is called here.
//operator < of MyTest is called here.
//operator < of MyTest is called here.
//The count of the map is 3
//key = 2, value = 2
//key = 5, value = 5
//key = 10, value = 10
从上面的输出结果可以看到MyTest的小于操作符重载函数被多次调用,而且该函数的逻辑也确实应用于map容器对象的排序中。有意思的是我们仅仅插入三个键值对到该map容器,然而该函数却被调用5次,这是为什么呢?很简单,和Java的compareTo方法的返回值不同,该方法的返回值为布尔类型,只能表示小于或者不小于,无法标明新对象的键值和容器中已经存在对象的键值是否相等。为了弥补这一问题,在新对象被插入到容器中的正确位置之前,map容器的insert方法需要从正反两个方向将新元素的键值与容器中部分键对象进行比较,如果在与同一个对象进行两次比较之后均返回true,则证明该键值已经存在,否则将新对象插入指定的位置。
2)在上面的示例代码中,map<MyTest,int>类型的键类型为MyTest对象类型,因此在每次插入新数据时都会产生一次键对象的拷贝构造,从而影响了插入效率。如果插入的是对象指针类型,则可以避免对象copy的发生,然而不幸的是,less<Key>会将对象指针视为整型,因此MyTest的小于操作符重载将不会被调用,那么我们也无法得到我们期望的排序结果,因为less<Key>只是基于指针地址做了简单而毫无意义的整数比较。那么该如何修订这一问题呢?见如下代码示例。
using namespace std;
class MyTest
{
public:
MyTest(int key) {
_key = key;
}
~MyTest() {}
public:
int _key;
};
struct MyTestComparator {
bool operator()(MyTest* first,MyTest* second) const {
printf("operator() of MyTestComparator is called here.
");
return first->_key - second->_key < 0;
}
};
using namespace std;
int main()
{
MyTest* mt0 = new MyTest(0);
MyTest* mt2 = new MyTest(2);
MyTest* mt1 = new MyTest(1);
map<MyTest*,int,MyTestComparator> mtMap;
mtMap.insert(make_pair(mt0,0));
mtMap.insert(make_pair(mt2,2));
mtMap.insert(make_pair(mt1,1));
printf("The count of map is %d.
",mtMap.size());
map<MyTest*,int,MyTestComparator>::iterator it = mtMap.begin();
for (; it != mtMap.end(); ++it) {
printf("key = %d, value = %d
",(*it).first->_key,(*it).second);
delete (*it).first;
}
return 0;
}
//operator() of MyTestComparator is called here.
//operator() of MyTestComparator is called here.
//operator() of MyTestComparator is called here.
//operator() of MyTestComparator is called here.
//operator() of MyTestComparator is called here.
//operator() of MyTestComparator is called here.
//operator() of MyTestComparator is called here.
//operator() of MyTestComparator is called here.
//The count of the map is 3
//key = 0, value = 0
//key = 1, value = 1
//key = 2, value = 2
在上面的代码中我们并没有使用map中缺省的less<Key>对象来比较容器中的键对象,而是自己重新定义了一个类来专门比较MyTest*类型的键。这一点有些类似于Java中的Comparator<T>接口。
后我们简单的总结一下Java和C++的泛型技术,由于C++是在语言设计之初已经将模板和泛型等特征考虑了进来,而Java则是半路出家,因此C++在这方面的支持也更灵活,更具伸缩性,在运行时也更加高效。

sales@spasvo.com