今天打算用C++模拟一下Java的Object对象。需求很简单,通过一个自定义用户类型包装一个内建类型,并提供equals、hashCode、=和== 4种函数。

源码如下:

#pragma once
#ifndef ENTITY_H_
#define ENTITY_H_
#include <functional>
template<typename T>
class Entity {
private:
T obj;
Entity(const Entity&);
public:
Entity(T t) :obj(t) {}; bool equals(Entity& other) {
std::hash<T> tohash;
return tohash(obj) == other.hashCode();
} size_t hashCode() {
std::hash<T> tohash;
return tohash(obj);
} Entity<T>& operator=(const Entity& rv) {
obj = rv.obj;
return *this;
} friend bool operator==(const Entity& left, const Entity& right) {
return left.hashCode() == right.hashCode();
}
}; #endif // !ENTITY_H_

C++11 提供了Hash方法正好拿来使用,可是在测试==的时候却发现编译器报错:“size_t Entity<int>::hashCode(void)”: 不能将“this”指针从“const Entity<int>”转换为“Entity<int> &”。说实话,平时Java用习惯了,猛然看见C++的报错信息真是一脸懵逼。后来在网上查了一些资料逐渐明白了个中缘由。

首先修改代码:

size_t hashCode() const {
std::hash<T> tohash;
return tohash(obj);
}

测试通过!做法很简单,但是要说明清楚这个问题,我们还得从对象方法与函数的区别谈起。

1. 函数与方法

函数是一个很原始的概念,在古代面向对象的语言还没有诞生。大家为了封装一些公共算法发明了函数这个概念,通常是根据实参经过函数体返回一个计算结果,并且实参要和形参对应。后来,面向对象的语言出现了,大家开始考虑让对象实施某些行为,这就是——方法。本质上,函数叫function和方法叫method。对象方法之于普通函数的最大区别是,它可以直接访问对象内部的成员属性(field)。在Java中我们通过this.field的方式就能够访问,在C++中更普遍的做法是this->field。这里就很奇怪了,为什么在method内部能直接使用this呢?原因是语言在编译过程中,编译器将对象(this)作为参数置入了method中。因此实际上,method的真实形象应该是这样的:method(this, args)。熟悉面向过程语言特性的朋友一定清楚,如果不用面向对象的思想实际上也可以用function模拟method,即也是将对象本身作为参数传递给function。

2. function(args) const

const blob b(2);

这里,b是类型blob的一个const对象。它的构造函数被调用,并且参数为“2”。由于编译器强调对象为const,因此它必须保证对象的数据成员(fields)在其生命周期内不被改变。然而,仅仅是在类声明中给出const还不能保证成员函数按声明的方式去做。所以,编译器会强制程序员在定义函数时重申const。这就是function(args) const的由来。

3. 结论

在明白了以上两点以后,我们再回到本例中。由于operator==(const Left& lv, const Right& rv)在函数中要求提供的两个参数对象都必须是const类型。因此在整个函数体中,这些对象执行的方法也必须是const类型。然而现在我们知道成员函数会隐式的调用对象本身,换句话说hashCode()方法会分别调用Left与Right,而这个方法并没有被重申为const。这就出现了开头看到的那段异常:“size_t Entity<int>::hashCode(void)”: 不能将“this”指针从“const Entity<int>”转换为“Entity<int> &”!

见微知著——从自定义类型的operator==说起的更多相关文章

  1. map以自定义类型当Key

    关于map的定义: template < class Key, class T, class Compare = less<Key>, class Allocator = alloc ...

  2. 《精通C#》自定义类型转化-扩展方法-匿名类型-指针类型(11.3-11.6)

    1.类型转化在C#中有很多,常用的是int类型转string等,这些都有微软给我们定义好的,我们需要的时候直接调用就是了,这是值类型中的转化,有时候我们还会需要类类型(包括结构struct)的转化,还 ...

  3. 关于set或map的key使用自定义类型的问题

    我们都知道set或map的key使用自定义类型时必须重载<关系运算符 但是,还有一个条件,所调用重载的小于操作符,使用的对象必须是const 而对象调用的方法也必须是const的 1 #incl ...

  4. Qt之创建自定义类型

    摘要: 简述 当使用Qt创建用户界面时,特别是那些带有特殊控制和特征的界面时,开发者通常需要创建新数据类型来扩展或替换Qt现有的的值类型集合. 标准类型,比如:QSize.QColor和QString ...

  5. [转]std::set、自定义类型与比较函数

    转自:http://www.189works.com/article-42025-1.html 怎样在set中放入自定义类型?这个问题通过谷歌就可以得到不少答案:1.定义一个函数对象并在定义set的时 ...

  6. QSet使用及Qt自定义类型使用QHash等算法

    版权声明:若无来源注明,Techie亮博客文章均为原创. 转载请以链接形式标明本文标题和地址: 本文标题:QSet使用及Qt自定义类型使用QHash等算法     本文地址:http://techie ...

  7. Qt自定义类型使用QHash等算法(Qt已经自定义了34种类型,包括int, QString, QDate等基本数据类型)

    自定义类型 #include <QCoreApplication> #include <QSet> #include <QDebug> class testCust ...

  8. 在set中放入自定义类型

    这件事情的起因是在学习背包问题时突然想到了一种算法,分析了一下应该是n^2logn复杂度的,当然比dp慢.但是既然想到了就实现了下: #include<bits/stdc++.h> usi ...

  9. C#简单问题,不简单的原理:不能局部定义自定义类型(不含匿名类型)

    今天在进行代码测试时发现,尝试在一个方法中定义一个委托,注意是定义一个委托,而不是声明一个委托变量,在编写的时候没有报错,VS也能智能提示,但在编译时却报语法不完整,缺少方括号,但实际查询并没有缺少, ...

随机推荐

  1. 安装spark单机环境

    (假定已经装好的hadoop,不管你装没装好,反正我是装好了) 1 下载spark安装包 http://spark.apache.org/downloads.html 下载spark-1.6.1-bi ...

  2. K:java中的hashCode和equals方法

      hashCode和equals方法是Object类的相关方法,而所有的类都是直接或间接的继承于Object类而存在的,为此,所有的类中都存在着hashCode和equals.通过翻看Object类 ...

  3. Python 实现接口类的两种方式+邮件提醒+动态导入模块+反射(参考Django中间件源码)

    实现接口类的两种方式 方式一 from abc import ABCMeta from abc import abstractmethod class BaseMessage(metaclass=AB ...

  4. libcurl的使用

    http://blog.csdn.net/ixiaochouyu/article/details/47998267

  5. java 数据格式验证类

    作为一个前端,懂一点java,php之类的,甚好. 我所在的项目前端采用的就是java的spring mvc框架,所以我们也写java,掐指一算,也快一年了. 前端而言,验证是一个坎,绕不过去的,前面 ...

  6. 3、UML建模技术

    UML(统一建模语言)是当前软件开发中使用最为广泛的建模技术之一,通过使用UML可以构造软件系统的需求模型(用例模型).静态模型.动态模型和架构模型 UML类图 1.UML类图图示 在UML中,类使用 ...

  7. Docker三十分钟快速入门(上)

    一.背景 ​ 最近,Docker技术真是一片火热,它的出现也弥补了虚拟机资源消耗过高的问题,直接让虚拟化技术有了质的飞跃.那么本文我们来聊一聊Docker,和大家一起认识Docker,简单入门Dock ...

  8. PyQt4 开发入门

    参考资料:PyQt4教程

  9. dom4j 间隔插入节点 处理复杂的xml文档

    前几周跟着老师做了一个小项目,个人主要负责xml文档处理,处理过程还是比较复杂的.此外这篇文章并不是讲基本的dom4j读写xml文档, 所以阅读此文的前提是你已经有了dom4j或jdom等处理xml文 ...

  10. 安装adb之后出现 找不到设备的情况

    adb 地址 https://pan.baidu.com/s/1sln2IZF     安装adb之后出现 找不到设备的情况   1.配置adb的环境变量 2.修改android_winusb.inf ...