运算符重载(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

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

  1. c++入门之—运算符重载和友元函数

    运算符重载的意义是:将常见的运算符重载出其他的含义:比如将*重载出指针的含义,将<<与cout联合使用重载出输出的含义,但需要认识到的问题是:运算符的重载:本质仍然是成员函数,即你可以认为 ...

  2. C++ 运算符重载时,将运算符两边对象交换问题.

    在C++进行运算符重载时, 一般来讲,运算符两边的对象的顺序是不能交换的. 比如下面的例子: #include <iostream> using namespace std; class ...

  3. C#高级编程笔记2016年10月12日 运算符重载

    1.运算符重载:运算符重重载的关键是在对象上不能总是只调用方法或属性,有时还需要做一些其他工作,例如,对数值进行相加.相乘或逻辑操作等.例如,语句if(a==b).对于类,这个语句在默认状态下会比较引 ...

  4. C++运算符重载

    C++运算符重载 基本知识 重载的运算符是具有特殊名字的函数,他们的名字由关键字operator和其后要定义的运算符号共同组成. 运算符可以重载为成员函数和非成员函数.当一个重载的运算符是成员函数时, ...

  5. 标准C++之运算符重载和虚表指针

    1 -> *运算符重载 //autoptr.cpp     #include<iostream> #include<string> using namespace std ...

  6. python运算符重载

    python运算符重载就是在解释器使用对象内置操作前,拦截该操作,使用自己写的重载方法. 重载方法:__init__为构造函数,__sub__为减法表达式 class Number: def __in ...

  7. PoEduo - C++阶段班【Po学校】-Lesson03-5_运算符重载- 第7天

    PoEduo - Lesson03-5_运算符重载- 第7天 复习前面的知识点 空类会自动生成哪些默认函数 6个默认函数    1  构造  2  析构   3  赋值  4 拷贝构造  5 oper ...

  8. 不可或缺 Windows Native (24) - C++: 运算符重载, 自定义类型转换

    [源码下载] 不可或缺 Windows Native (24) - C++: 运算符重载, 自定义类型转换 作者:webabcd 介绍不可或缺 Windows Native 之 C++ 运算符重载 自 ...

  9. 我的c++学习(8)运算符重载和友元

    运算符的重载,实际是一种特殊的函数重载,必须定义一个函数,并告诉C++编译器,当遇到该运算符时就调用此函数来行使运算符功能.这个函数叫做运算符重载函数(常为类的成员函数). 方法与解释 ◆ 1.定义运 ...

随机推荐

  1. C++学习笔记(三)之函数库

    1.标准库函数 begin end begin 返回数组首地址 end   返回数组尾地址 2.const 在声明变量时对变量限制为只读,不允许修改 const int i = 5; 单个const作 ...

  2. Python批量下载电视剧电影--自己动手丰衣足食

    前言 为了看美剧<天蝎>,在电影天堂找到了,于是就想下载下来好好欣赏. 废话不说了,直接上代码. 代码 import requests,re,os,time url = "htt ...

  3. js文件中引用其他js文件

    这一个功能的作用是做自己的js包时,可以通过引入一个整体的js文件而引入其他js. 只需要在总体的js加上这一句话 document.write("<script type='text ...

  4. Linux 压力测试及内存检测

    常用的 Stress / Performance 工具 http://benjr.tw/532 Linux中的常用内存问题检测工具 https://blog.csdn.net/jinzhuojun/a ...

  5. UI设计四要素

    信息.样式.布局.交互. +层次: UI所有的工作都可以从这几个方面入手.

  6. js延时加载的方法

    js的延迟加载有助与提高页面的加载速度,以下是延迟加载的几种方法: 1.使用setTimeout延迟方法的加载时间 延迟加载js代码,给网页加载留出更多时间 <script type=" ...

  7. Functional language 函数

    一.什么是函数式语言?       函数式语言一类程序设计语言,是一种非冯·诺伊曼式的程序设计语言.函数式语言主要成分是原始函数.定义函数和函数型.这种语言具有较强的组织数据结构的能力,可以把某一数据 ...

  8. oracle_backup

    #!/bin/bash DAYS=`date +"%Y%m%d"` . /home/oracle/.bash_profile # /home/opt/oracle/11g/bin/ ...

  9. mysql导出数据到excel的两种方式

    使用第一种方式如果数据中有换行符的话会自动换行,但使用第二种方式就不会出现这种效果了.两种方式自己选择哈 1:select * from into outfile 'c:/Users/a.xls' t ...

  10. .Net Core2.2 + EF Core + DI,三层框架项目搭建教程

    笔记: 近两年.Net Core发展的很快,目前最新版为3.0预览版,之前在网上买了一本1.1版书籍都还没来得及看呢,估计现在拿出来看也毫无意义了.已多年.net工作经验,看书不如直接实际上手来得快, ...