玩转C++运算符重载
2014-12-18 00:00
225 查看
运算符重载语法:返回值类型 operator运算符(参数列表) { 代码逻辑。。。 }
C++中的运算符重载是通过函数来实现的,可以将重载的运算符看作是类成的一个成员函数,向普通函数一样调用。如重载String类的 + 运算符,调用的时候可以这样:
从上述代码中可以看出,operator+就像是String类的一个函数,可以像普通函数一样调用,将要相加的字符串对象作为实参传递给函数即可。所以从这可以得出一个函数重载的步聚:(以上述+重载为例)
1、写出运算符的函数原型
str1.operator+(str2);
从这可以得知,+ 需要两个操作数,str1和str2(即两个字符串对象),返回值类型为String对象(加法运算后的结果)。由于是作为类的成员函数重载,所以str1在进行 + 运算时作为this指针传给函数,函数只需要一个参数即可,即被相加的字符串对象str2。
2、写出函数声明
从函数原型可以得出函数声明:String operator+(const String &str);
3、实现函数细节
下面这个示例重载了字符串操作的常用操作符:
运算符重载注意事项:
友元函数重载运算符时需要传递所有操作数
成员函数重载,会将操作数本身做为this指针作为参数传入函数,如果是多元操作符,只需与它被操作的数传入函数即可
= 号重载时,如果对象中有新分配内存的成员,要先delete,再new,如果要支持连等操作,需要返回对象本身的引用
函数返回值作左值时,返回值必须为引用
只有C++预定义的操作符集中的操作符才可以被重载(不能自己随便写一个操作符,如:+-)
重载操作符不能改变操作符的优先级,例如:先乘徐,后加减
重载操作符不能改变操作数的个数
以下几种运算符不能被重载:
. :成员选择运算符
:: :作用域运算符
* : 指针运算符
# :预处理标志
?: :三目运算符,没有确定性,重载没有意义
C++中的运算符重载是通过函数来实现的,可以将重载的运算符看作是类成的一个成员函数,向普通函数一样调用。如重载String类的 + 运算符,调用的时候可以这样:
class { // ..... String operator+(const String &str) { .... } } String str1 = "hello "; String str2 = "cplusplus"; String str3 = str1.operator+(str2);
从上述代码中可以看出,operator+就像是String类的一个函数,可以像普通函数一样调用,将要相加的字符串对象作为实参传递给函数即可。所以从这可以得出一个函数重载的步聚:(以上述+重载为例)
1、写出运算符的函数原型
str1.operator+(str2);
从这可以得知,+ 需要两个操作数,str1和str2(即两个字符串对象),返回值类型为String对象(加法运算后的结果)。由于是作为类的成员函数重载,所以str1在进行 + 运算时作为this指针传给函数,函数只需要一个参数即可,即被相加的字符串对象str2。
2、写出函数声明
从函数原型可以得出函数声明:String operator+(const String &str);
3、实现函数细节
String String::operator+(const String &str) { if (str.buff == nullptr) { return *this; } size_t totallen = str.len + this->len + 1; char *buff = new char[totallen]; strcpy(buff, this->buff); strcat(buff, str.buff); String temp(buff); return temp; }
下面这个示例重载了字符串操作的常用操作符:
//
// String.h
// C++运算符重载
//
// Created by 杨信 on 14-5-8.
// Copyright (c) 2014年 yangxin. All rights reserved.
//
#ifndef __C______String__
#define __C______String__
#include <iostream>
using namespace std;
class String
{
private:
char *buff;
size_t len;
public:
String();
// 用一个字符串初始化对象
String(const char *buff);
// 拷贝构造
String(const String &str);
// 析构
~String();
// 设置字符串内容
void setString(const char *buff);
// 获取字符串的长度
size_t length() const;
// 获取字符串内容
char * getStr() const;
// 比较两个字符串是否相等
bool operator==(String &str);
// 比较两个字符串是否不相等
bool operator!=(String &str);
// 比较两个字符串的大小
bool operator>(String &str);
// 比较两个字符串的大小
bool operator<(String &str);
// 获取或修改字符串中的某一个字符
char& operator[](int index);
// 赋值构造函数
String& operator=(const String &str);
// 两个字符串相加
String operator+(const String &str);
// 字符串累加
String& operator+=(const String &str);
// 从输入流中获取字符串
friend istream& operator>>(istream &input, String &str);
// 将字符串输出到输出流
friend ostream& operator<<(ostream &output, const String &str);
};
#endif /* defined(__C______String__) */
//
// String.cpp
// C++运算符重载
//
// Created by 杨信 on 14-5-8.
// Copyright (c) 2014年 yangxin. All rights reserved.
//
#include "String.h"
#include <string>
#include <cassert>
#include <cmath>
String::String()
{
this->buff = nullptr;
this->len = 0;
}
// 用一个字符串初始化对象
String::String(const char *buff):buff(nullptr), len(0)
{
setString(buff);
}
// 拷贝构造
String::String(const String &str)
{
setString(str.buff);
}
// 析构
String::~String()
{
// 释放内存
if (this->buff != nullptr)
{
delete[] buff;
buff = nullptr;
len = 0;
}
}
void String::setString(const char *buff)
{
if (buff == nullptr)
{
return;
}
if (this->buff != nullptr) {
delete[] this->buff;
this->buff = nullptr;
this->len = 0;
}
size_t len = strlen(buff);
this->buff = new char[len + 1];
this->len = len;
strcpy(this->buff, buff);
}
// 获取字符串的长度
size_t String::length() const
{
return this->len;
}
// 获取字符串内容
char * String::getStr() const
{
return this->buff;
}
// 获取或修改字符串中的某一个字符
char& String::operator[](int index)
{
assert(index < this->len);
return this->buff[index];
}
// 比较两个字符串是否相等
bool String::operator==(String &str)
{
if (this->len != str.len)
{
return false;
}
for (int i = 0; i < this->len; ++i)
{
if (this->buff[i] != str[i])
{
return false;
}
}
return true;
}
// 比较两个字符串是否不相等
bool String::operator!=(String &str)
{
return !(*this == str);
}
// 比较两个字符串的大小
bool String::operator>(String &str)
{
char *pstr = this->buff;
char *pstr2 = str.buff;
while (*pstr != '\0' && *pstr2 != '\0')
{
if (*pstr > *pstr2) {
return true;
}
pstr++;
pstr2++;
}
return false;
}
// 比较两个字符串的大小
bool String::operator<(String &str)
{
return !(*this > str);
}
// 赋值构造函数
String& String::operator=(const String &str)
{
setString(str.buff);
return *this;
}
// 两个字符串相加
String String::operator+(const String &str) { if (str.buff == nullptr) { return *this; } size_t totallen = str.len + this->len + 1; char *buff = new char[totallen]; strcpy(buff, this->buff); strcat(buff, str.buff); String temp(buff); return temp; }
// 字符串累加
String& String::operator+=(const String &str)
{
if (str.buff == nullptr)
{
return *this;
}
// 创建一个临时缓冲区,存储对象本身的字符串和相加的字符串
size_t len = this->len + str.length();
char *temp = new char[len + 1];
strcpy(temp, this->buff);
strcat(temp, str.buff);
// 设置新的字符串给对象本身
setString(temp);
return *this;
}
// 从输入流中获取字符串
istream& operator>>(istream &input, String &str)
{
// 在堆区创建临时缓冲区,接收用户输入
int size = 1024 * 10;
char *tempbuff = new char[size];
memset(tempbuff, 0, size);
// 获取用户输入
input.getline(tempbuff, size);
// 将临时缓冲中的字符串保存到str对象的字符串缓冲区中
str.setString(tempbuff);
// 释放临时缓冲区数据
delete[] tempbuff;
tempbuff = nullptr;
return input;
}
// 将字符串输出到输出流
ostream& operator<<(ostream &output, const String &str)
{
output << str.getStr();
return output;
}
// 测试用例
//
// main.cpp
// String(运算符重载)
//
// Created by 杨信 on 14-5-8.
// Copyright (c) 2014年 yangxin. All rights reserved.
//
#include <iostream>
#include "String.h"
#include <cmath>
using namespace std;
int main(int argc, const char * argv[])
{
// 初始化
String str1("helloz");
String str2("helloz");
// 获取字符中内容
cout << str1.getStr() << endl;
// 获取字符串的长度
cout << "长度:" << str1.length() << endl;
// 获取第字符串中的第一个字符
cout << "第1个字符:" << str1[0] << endl;
// 比较两个字符串是否相等,相等返回1,否则返回0
bool isequal = str1 == str2;
cout << isequal << endl;
// 比较两个字符串的大小,str1大于str2返回1,否则返回0
cout << (str1 > str2) << endl;
// 修改字符串中的第2个字符为C
String s = "Hello";
s[1] = 'C';
cout << s << endl;
// 测试用一个字符串去初始化另外一个字符串
String str3 = str2;
cout << str3.getStr() << endl;
String str4;
str4 = str3;
cout << str4.getStr() << endl;
// 测试两个字符串相加
String str5 = str1 + str2;
cout << &str5 << endl;
cout << str5.getStr() << endl;
// 测试字符串连等
String str6;
String str7 = str6 = str5;
cout << str6.getStr() << " | " << str7.getStr() << endl;
// 测试字符串累加
String str8 = "i love c++ ";
str8 += "i love c ";
cout << str8.getStr() << endl;
// 从输入流读取字符串
String str9;
cout << "Please a string:";
cin >> str9;
// 将字符串输出到输出流
cout << str9 << endl;
return 0;
}
运算符重载注意事项:
友元函数重载运算符时需要传递所有操作数
成员函数重载,会将操作数本身做为this指针作为参数传入函数,如果是多元操作符,只需与它被操作的数传入函数即可
= 号重载时,如果对象中有新分配内存的成员,要先delete,再new,如果要支持连等操作,需要返回对象本身的引用
函数返回值作左值时,返回值必须为引用
只有C++预定义的操作符集中的操作符才可以被重载(不能自己随便写一个操作符,如:+-)
重载操作符不能改变操作符的优先级,例如:先乘徐,后加减
重载操作符不能改变操作数的个数
以下几种运算符不能被重载:
. :成员选择运算符
:: :作用域运算符
* : 指针运算符
# :预处理标志
?: :三目运算符,没有确定性,重载没有意义
相关文章推荐
- 玩转C++运算符重载
- 玩转C++运算符重载
- 在KCloud上轻松“玩转”Docker
- 玩转Android monkey之多参数实战
- 使用 Eclipse 玩转 C、C++
- 大神教你几招玩转Bootstrap框架技术
- 玩转lua:搞懂lua潜规则
- 企业运维—CentOS7玩转DHCP服务
- 带你玩转Visual Studio——带你管理多种释出版本
- 玩转微信支付(python)
- 玩转Windows服务系列——使用Boost.Application快速构建Windows服务
- 企业运维—玩转 windows server 2016 DNS服务
- (转自博客园-雲霏霏)5天玩转C#并行和多线程编程 —— 第三天 认识和使用Task
- 如何使用 stack?- 每天5分钟玩转 Docker 容器技术(112)
- 玩转Visual Studio-理解微软的预编译头技术
- JAVA初识之玩转while 与for循环
- 《用Python玩转数据》第1周学习笔记(Part2)
- Windows玩转Caffe系列之模型应用(一): 新建MFC工程,窗口界面中应用现有模型
- 15天玩转redis —— 第一篇 开始入手
- 干货丨手把手带你玩转机器学习和深度学习