C++运算符重载的妙用

运算符重载(Operator overloading)是C++重要特性之中的一个,本文通过列举标准库中的运算符重载实例,展示运算符重载在C++里的妙用。详细包含重载operator<<,operator>>支持cin,cout输入输出。重载operator[],实现下标运算。重载operator+=实现元素追加;重载operator()实现函数调用。假设你对C++的运算符重载掌握的游刃有余。那就无需继续往下看了。

运算符重载带来的优点就是——让代码变得简洁。以下将展示几个标准库因使用运算符重载而是代码简洁的实例。

Hello, World与operator<<

刚学C++时看到的第一个C++程序就是Hello World,它当时长得这样:

#include <iostream>

using namespace std;

int main(int argc, char *argv[])
{
	cout << "Hello, world!" << endl;
	return 0;
}

当时。我以为 cout << sth 和 cin >> xxx 这是“必须的格式”。

而其实,这仅仅是运算符重载在标准库里的一个缩影而已。这里实际调用的是<string>定义的:

  extern template ostream& operator<<(ostream&, const char*);

容器与operator[]

以下展示vector和map因提供了operator[]而使程序变得简洁的实例。

vector::operator[]

STL 容器(Container)中的vector,map,都提供了operator[],对于vector,operator[]使得它的使用方法“和数组类似”,就是能够用下标訪问vector的元素:

	int firstInt = ivec[0]; // operator[]
	ivec[0] = 1; //

假设没有运算符重载。相同的功能非常可能就要写成:

	int firstInt = ivec.get(0);
	ivec.set(0, 1);

这就不再像数组那么“亲切”了。

以下的代码是求vector<int> ivec内全部元素和的代码:

	int sum = 0;
	for(int i=0; i < ivec.size(); i++) {
		sum += ivec[i];
	}

map::operator[]

类似的,operator[]使map很好用。比方使用标准库map和string的单词统计的核心代码仅仅有例如以下几行:

	string word;
	map<string, int> dict;

	while(cin >> word)
	{
		dict[word]++; // operator[]
	}

对于map,假设没有operator[],那上面的 dict[word]++ 一行要写成:

map<string, int>::iterator it = dict.find(word);
if(it != dict.end()) {
	it->second++;
}
else {
	dict.insert(make_pair(word, 1));
}

能够从cplusplus.com能够上看到,map的operator[]相当于:

(*((this->insert(make_pair(x,T()))).first)).second

这样的写法看起来非常难理解,能这么写是由于map::insert是有返回值的:

pair<iterator,bool> insert ( const value_type& x );

使用C++标准库实现的"单词统计",整个程序例如以下:

#include <cstdio>
#include <iostream>
#include <map>
#include <string>

using namespace std;

int main(int argc, char *argv[])
{
	string word;
	map<string, int> dict;

	while(cin >> word)
	{
		dict[word]++;
	}

	// output:
	for(map<string, int>::iterator it = dict.begin(); it != dict.end(); ++it)
	{
		cout << it->first << "\t" << it->second << "\n";
	}
	return 0;
}

这段程序不仅完毕了“单词统计”,还依照单词的字典顺序进行输出,这些全依赖于标准库的运算符重载。

迭代器与operator++

上面“单词统计”的代码。已经使用设计到了iterator,正是“迭代器”。简单地说,迭代器就是有指针功能的class类型;而它的“指针”功能。正是经由运算符重载实现的。

比方以下代码能够输出vecotr<int> ivec的所有元素:

	for(vector<int>::iterator it = ivec.begin();
		it != ivec.end(); // operator!=
		it++) { // operator++
			printf("%d\n",
				*it); // operator*
		}

这段短短的代码调用了iterator重载的三个operator。运算符重载使得这里for循环的写法和数组的迭代方式类似。

C/C++的原始指针支持的运算有:

  1. 解引用(dereference)运算
  2. 取成员(member access)运算
  3. 自增(increment)、自减(decrement)运算
  4. 算数加减运算

实现以上功能。相应的运算符重载成员函数分别为:

  1. operator*()
  2. operator->()
  3. operator++()、operator--()
  4. operator+(int)、operator-(int)

iterator至少实现了1,2,3中的一个。

所有重装就能全然模拟指针支持的语法。要实现和指针类似的功能还需实现对于的函数内容。

除了iterator。智能指针(shared_ptr等)也重载了以上几个运算符,使得他们用起来和原始指针很相似(语法形式上);但它们的“自己主动引用计数”能力除了借助了运算符重载。很多其它的应当归功与C++的RAII惯使用方法,兴许我将专门写一篇关于RAII妙用的文章来解释shared_ptr是怎样实现“自己主动引用计数”的。

关于迭代器,最为激进的莫过于:

copy(istream_iterator<char>(cin), istream_iterator<char>(), ostream_iterator<char>(cout, "")); 

string与operator+=

标准库的string,提供了operator[],使得用户能够使用下标运算符訪问字符串中的字符。这和char array, char pointer无异。比如:

str1[0] = str2[0];
str2[0] = ‘A‘;

除此之外,string还提供了重载了的operator+=。能够向已有的string对象追加字符和字符串(包含char array,char pointer)。

比如:

str1 += ‘!‘;
str1 += str2;
str1 += "literal string";

函数对象与operator()

在<algorithm>提供的众多算法中,大多都有两个版本号。当中一个版本号多出一个叫做Function Object的參数,比方sort:

template <class RandomAccessIterator>
  void sort ( RandomAccessIterator first, RandomAccessIterator last );

template <class RandomAccessIterator, class Compare>
  void sort ( RandomAccessIterator first, RandomAccessIterator last, Compare comp );

comp就被称作是Function Object。

究竟什么是Function Object呢?字面理解就是一个能够当函数调用的对象。事实上就是一个重载了operator()的对象,比方要实现对一个vector<string>依照字符串长度对元素排序。能够传入一个这个Functor的实例:

struct StrLenComp
{
	bool operator()(const string& a, const string& b) {
		return a.length() < b.length();
	}
};

当然,假设你对C++11非常熟悉。这个Functor的Function Object全然能够用一行的lambda表达式表示:

[](const string& a, const string& b){ return a.length() < b.length(); }

小结

上面列出的是标准库中最广为认知的运算符重载的样例。但标准库使用运算符重载的地方远不止此。

实质

C++中运算符重载实际上和函数重载、成员函数重载并没有两样。仅仅是写起来更简洁一点罢了。

编译时,它们都会被改动为编译器内部的名称,也相同支持“重载”——參数列表不同。

代码实例

本文仅仅讲了运算符重载在C++中各种“奇妙”的使用方法。你是不是也摩拳擦掌,想要一展身手了?你是想要体验一把这些特性的“好用之处”。还是想要“自己动手”写几个运算符重载函数?预知怎样重载运算符。请移步:http://blog.csdn.net/xusiwei1236/article/details/39528813

时间: 2024-12-28 21:06:49

C++运算符重载的妙用的相关文章

关于运算符重载

运算符重载需遵循以下原则: 1.除了类所属关系运算符".".成员指针运算符".*".作用域运算符"::".sizeof运算符.三目运算符"?:"之外,C++中所有的运算符都可以进行重载 2.重载运算符限制在C++已有的运算符范围内,不允许创建新的运算符 3.重载之后的运算符不能改变运算符的优先级和结合性,也不能改变运算符的操作数的个数及语法结构 4.运算符重载不能改变运算符用于内置类型的对象的含义,只能用于自定义类型对象之间,

运算符重载

关键字:operator 相见:<高质量程序设计指南> P255 如果运算符被重载为全局函数,那么只有一个参数的运算符叫做一元运算符,有两个参数的运算符叫做二元运算符. 如果运算符被重载为类的成员函数,那么一元运算符没有参数(但是++和--运算符的后置版本除外),二元运算符只有右侧参数,因为对象自己成了左侧参数. 运算符重载的特殊性 如果重载为成员函数,则this对象发起对它的调用 如果重载为全局函数,则第一个参数发起对它的调用 禁止用户发明该语言运算符集合中不存在的运算符 除了函数调用运算符

C++ 运算符重载

C++中预定义的运算符的操作对象只能是基本数据类型,实际上,对于很多用户自定义类型,也需要有类似的运算操作.比如对象a和对象b, 那么 a+b 就需要用户自己定义它怎么相加,这时就用到了运算符重载. 运算符重载规则如下: ①. C++中的运算符除了少数几个之外,全部可以重载,而且只能重载C++中已有的运算符. ②. 重载之后运算符的优先级和结合性都不会改变. ③. 运算符重载是针对新类型数据的实际需要,对原有运算符进行适当的改造.一般来说,重载的功能应当与原有功能相类似,不能改变原运算符的操作对

Kotlin中复合赋值(+=,-=,……)运算符重载

本篇建立在已经了解了kotlin中运算符重载的理念以及如何实现的基础上. 来我们首先写一个简单的类,然后重载运算符+,+=,-,-=这个几个运算符.代码如下: data class Point(var x: Int, var y: Int) { operator fun plus(point: Point): Point { return Point(this.x + point.x, this.y + point.y) } operator fun plusAssign(point: Poin

第十章 运算符重载

第十章 运算符重载 1.运算符重载的方法 (实质:函数重载) *一般格式: 函数类型名operator 运算符名称(参数表){函数体:} 2.运算符重载的规则 *不允许定义新的运算符 *允许重载的运算符 双目运算符 +(加法)  - (减法)  * (乘法) / (除法)   %(取模) 关系运算符 ==(等于) != (不等)  <   >   <=   >= 逻辑运算符 ||(或)   && (与)  !(非) 单目运算符 + (正)  -(负)   *(指针)

网易云课堂_C++开发入门到精通_章节4:运算符重载

课时23运算符重载 运算符重载 重载赋值运算符 Person& Person::operator=(const Person& other) { //检查自赋值 if (this == &other) { return *this; } //释放原有的内存资源 delete[]m_data; int length = strlen(other.m_data); m_data = new char[length + 1]; strcpy(m_data, other.m_data);

关于c++的运算符重载那些事

搞c++有一段时间了,今天突然要重载一个运算符,发现自己有点忘了,遂查查资料做一下c++运算符重载的小总结. 一.何为运算符重载 运算符的重载是c++语言特有的,java什么的是没有运算符重载的,所以运算符重载在笔试面试中有可能成为c++的高频考点.运算符重载就是重新定义运算符的意义,如常用的+,-,×,÷都是可以重载的.运算符重载使用的是关键字operator,表现形式是:                                                            

C++:运算符重载函数之&quot;++&quot;、&quot;--&quot;、&quot;[ ]&quot;的应用

5.2.5 "++"和"--"的重载 对于前缀方式++ob,可以用运算符函数重载为: ob.operator++() //成员函数重载 或 operator++(X &ob) //友元函数重载,其中ob为类X的对象的引用 对于后缀方式++ob,可以用运算符函数重载为: ob.operator++(int) //成员函数重载 或 operator++(X &ob,int) //友元函数重载,其中ob为类X的对象的引用 调用时,参数int一般被传递给值0

C++:运算符重载函数之成员运算符重载函数

5.2.3 成员运算符重载函数 在C++中可以把运算符重载函数定义为某个类的成员函数,称之为成员运算符重载函数. 1. 定义成员运算符重载函数的语法形式 (1)在类的内部,定义成员运算符重载函数的格式如下: 函数类型 operator 运算符(形参表) {       函数体 } (2)成员运算符重载函数也可以在类中声明成员函数的原型,在类外定义. 在类的内部,声明成员运算符重载函数原型的格式如下: class X{      ...      函数类型 operator运算符(参数表); };