自定义数据运算方法
复数加法
#include<iostream>
using namespace std;
class Complex {
public:
int a;
int b;
Complex(int a = 0, int b = 0) {
this->a = a;
this->b = b;
}
void printCom() {
cout << a << " + " << b << "i" << endl;
}
};
Complex myAdd(Complex& c1, Complex& c2) {
Complex tmp(c1.a + c2.a, c1.b + c2.b);
return tmp;
}
// operator+ 当作函数名
Complex operator+(Complex& c1, Complex& c2) {
cout << "加号重载" << endl;
Complex tmp(c1.a + c2.a, c1.b + c2.b);
return tmp;
}
void main() {
int a = 0, b = 0;
int c;
c = a + b; // 基础数据类型 编译器已知运算规则
Complex c1(1, 2), c2(3, 4);
Complex c3; // 用户自定义数据类型C++编译器不知道如何进行运算
// c++ 编译器提供机制,让程序员对自定义类型进行运算符操作
// 运算符重载
//c3 = c1 + c2;
// 1
//Complex c4 = myAdd(c1, c2);
// 2
/*Complex c4 = operator+(c1, c2);
c4.printCom();*/
// 3
Complex c4 = c1 + c2;
c4.printCom();
// 运算符重载本质是函数调用
}
1 运算符重载语法
类型 类名::operator op(参数表)
Complex operator+(Complex &c1, Complex &c2)
1 二元运算符重载
class Complex {
// 1 全局函数方法实现"+"重载
friend Complex operator+(Complex& c1, Complex& c2);
private:
int a;
int b;
public:
Complex(int a = 0, int b = 0) {
this->a = a;
this->b = b;
}
void printCom() {
cout << a << " + " << b << "i" << endl;
}
// 2 成员函数方法实现"-"重载
Complex operator-(Complex& c2) {
Complex tmp(this->a - c2.a, this->b - c2.b);
return tmp;
}
};
/*
全局函数、类成员函数方法实现重载步骤
写出函数名称
写出函数参数
完善返回值(引用,指针,元素)
*/
// 1 全局函数方法实现"+"重载
Complex operator+(Complex& c1, Complex& c2) {
cout << "加号重载" << endl;
Complex tmp(c1.a + c2.a, c1.b + c2.b);
return tmp;
}
void main() {
Complex c1(1, 2), c2(3, 4);
Complex c3 = c1 + c2;
c3.printCom();
Complex c4 = c1 - c2;
c4.printCom();
//1 全局函数方法实现"+"重载
// Complex operator+(Complex & c1, Complex & c2);
// 2 成员函数方法实现"-"重载
//c1.operator-(c2);
//operator(this, c2)
//Complex operator(Complex & c2);
}
结果
加号重载
4 + 6i
-2 + -2i
2 一元运算符重载
class Complex {
// 重载前置++
friend Complex& operator++(Complex& c1);
// 重载后置++
friend Complex operator++(Complex& c1, int);
private:
int a;
int b;
public:
Complex(int a = 0, int b = 0) {
this->a = a;
this->b = b;
}
void printCom() {
cout << a << " + " << b << "i" << endl;
}
// 前置--
Complex& operator--() {
this->a--;
this->b--;
return *this;
}
// 后置--
Complex& operator--(int) {
Complex tmp = *this;
this->a--;
this->b--;
return tmp;
}
};
/*
全局函数、类成员函数方法实现重载步骤
写出函数名称
写出函数参数
完善返回值(引用,指针,元素)
*/
// 前置++操作符,用全局函数实现
Complex& operator++(Complex& c1) {
c1.a++;
c1.b++;
return c1;
}
// 后置++操作符,用全局函数实现
Complex operator++(Complex& c1, int) {
Complex tmp = c1;
c1.a++;
c1.b++;
return tmp;
}
void main() {
Complex c1(1, 2), c2(3, 4);
// 前置++操作符,用全局函数实现
++c1;
c1.printCom();
// 前置--操作符,成员函数方法
--c1;
c1.printCom();
// 后置++操作符,用全局函数实现
c1++;
c1.printCom();
// 后置--操作符,成员函数方法
c1--;
c1.printCom();
}
2 全部改写为成员函数
class Complex {
private:
int a;
int b;
public:
Complex(int a = 0, int b = 0) {
this->a = a;
this->b = b;
}
void printCom() {
cout << a << " + " << b << "i" << endl;
}
// 2 成员函数方法实现"-"重载
Complex operator-(Complex& c2) {
Complex tmp(this->a - c2.a, this->b - c2.b);
return tmp;
}
// 前置--
Complex& operator--() {
this->a--;
this->b--;
return *this;
}
// 后置--
Complex& operator--(int) {
Complex tmp = *this;
this->a--;
this->b--;
return tmp;
}
// 成员函数方法实现"+"重载
Complex operator+(Complex& c2) {
cout << "加号重载" << endl;
Complex tmp(a + c2.a, b + c2.b);
return tmp;
}
// 前置++操作符,用成员函数实现
Complex& operator++() {
a++;
b++;
return *this;
}
// 后置++操作符,用成员函数实现
Complex operator++(int) {
Complex tmp = *this;
a++;
b++;
return tmp;
}
};
/*
全局函数、类成员函数方法实现重载步骤
写出函数名称
写出函数参数
完善返回值(引用,指针,元素)
*/
void main() {
Complex c1(1, 2), c2(3, 4);
/*Complex c3 = c1 + c2;
c3.printCom();
Complex c4 = c1 - c2;
c4.printCom();*/
//1 全局函数方法实现"+"重载
// Complex operator+(Complex & c1, Complex & c2);
// 2 成员函数方法实现"-"重载
//c1.operator-(c2);
//operator(this, c2)
//Complex operator(Complex & c2);
// 前置++操作符,用全局函数实现
++c1;
c1.printCom();
// 前置--操作符,成员函数方法
--c1;
c1.printCom();
// 后置++操作符,用成员函数实现
c1++;
c1.printCom();
// 后置--操作符,成员函数方法
c1--;
c1.printCom();
}
1 重载<< >>操作符(友元函数)
1 全局函数方法(只能用友元,不能用成员函数)
//void operator<<(ostream& out, Complex& c1) {
// out << c1.a << " + " << c1.b << "i " << endl;
//}
ostream& operator<<(ostream& out, Complex& c1) {
out << c1.a << " + " << c1.b << "i " << endl;
return out;
}
void main() {
Complex c1(1, 2), c2(3, 4);
cout << c1;
// 函数返回值当左值需要返回一个引用
// ostream类中添加.operator<< 只能用友元函数实现
cout << c1 << "abcd";
}
C++友元函数不要做 = () [] -> 重载
3 重载=操作符
成员函数重载=
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class Name {
public:
Name(const char* myp) {
m_len = strlen(myp);
m_p = (char*)malloc(m_len + 1);
strcpy(m_p, myp);
}
// copy构造函数,实现深拷贝
Name(const Name& obj1) {
m_len = obj1.m_len;
m_p = (char*)malloc(m_len + 1);
strcpy(m_p, obj1.m_p);
}
Name& operator=(Name& obj1) {
// 1 先释放旧内存
if (this->m_p != NULL) {
delete[] m_p;
m_len = 0;
}
// 2 根据obj1分配内存大小
this->m_len = obj1.m_len;
this->m_p = new char[m_len + 1];
// 3 把obj1赋值
strcpy(this->m_p, obj1.m_p);
return *this;
}
~Name() {
if (m_p != NULL) {
free(m_p);
m_p = NULL;
m_len = 0;
}
}
private:
int m_len;
char* m_p;
};
void objplay1() {
Name obj1("abcdefg");
Name obj2 = obj1; // 调用自己的构造函数 深拷贝
Name obj3("obj3");
obj3 = obj1; // 重构
obj1 = obj2 = obj3;
}
void main() {
objplay1();
}
4 重载数组下标[]
MyArray.h
#pragma once
#include<iostream>
using namespace std;
class Array {
public:
Array(int length);
Array(const Array& obj);
~Array();
void setData(int index, int value);
int getData(int index);
int length();
// 函数返回值当左值, 需要一个引用 重载[]
int& operator[](int i);
// 重载=
Array& operator=(Array& a1);
// 重载==
bool operator==(Array& a1);
// 重载!=
bool operator!=(Array& a1);
private:
int m_length;
int* m_space;
};
// 重载[] = == !=
MyArray.cpp
#include"MyArray.h"
Array::Array(int length) {
if (length < 0) {
length = 0;
}
m_length = length;
m_space = new int[m_length];
}
Array::Array(const Array& obj) {
this->m_length = obj.m_length;
this->m_space = new int[this->m_length]; // 分配内存空间
for (int i = 0; i < obj.m_length; i++) { // 数组元素复制
this->m_space[i] = obj.m_space[i];
}
}
Array::~Array() {
if (m_space != NULL) {
delete[]m_space;
m_length = 0;
}
}
void Array::setData(int index, int value) {
m_space[index] = value;
}
int Array::getData(int index) {
return m_space[index];
}
int Array::length() {
return m_length;
}
int& Array::operator[](int i) {
return m_space[i];
}
Array& Array::operator=(Array& a1) {
// 1 释放原来内存空间
if (this->m_space != NULL) {
delete[] m_space;
m_length = 0;
}
// 2 根据a1大小分配内存
m_length = a1.m_length;
m_space = new int[m_length];
// 3 拷贝数据
for (int i = 0; i < m_length; i++) {
//m_space[i] = a1.m_space[i];
m_space[i] = a1[i];
}
return *this;
}
bool Array::operator==(Array& a1) {
if (this->m_length != a1.m_length) {
return false;
}
for (int i = 0; i < m_length; i++) {
if (this->m_space[i] != a1[i]) {
return false;
}
}
}
bool Array::operator!=(Array& a1) {
/*if (this->m_length == a1.m_length) {
return false;
}
for (int i = 0; i < m_length; i++) {
if (this->m_space[i] == a1[i]) {
return false;
}
}*/
/*if (*this == a1) {
return false;
}
else {
return true;
}*/
return !(*this == a1);
}
TestArray.cpp
#include<iostream>
#include"MyArray.h"
using namespace std;
void main() {
Array a1(10);
cout << "打印a1" << endl;
for (int i = 0; i < 10; i++) {
//a1.setData(i, i);
// 函数返回值当左值, 需要一个引用
a1[i] = i;
}
for (int i = 0; i < 10; i++) {
/*cout<<a1.getData(i)<<" ";*/
cout << a1[i] << " ";
}
Array a2 = a1;
cout << "\n打印a2" << endl;
for (int i = 0; i < a2.length(); i++) {
cout << a2.getData(i) << " ";
}
Array a3(5);
/*{
a3 = a1;
a3 = a2 = a1;
cout << "\n打印a3" << endl;
for (int i = 0; i < 10; i++) {
cout << a3[i] << " ";
}
}*/
{
// 重载 ==
if (a3 == a1) {
cout << "\n==\n" << endl;
}
else {
cout << "\n!=\n" << endl;
}
}
{
// 重载 !=
if (a3 != a1) {
cout << "\n!=\n" << endl;
}
else {
cout << "\n==\n" << endl;
}
}
}
5 重载括号()
class F {
public:
int operator()(int a, int b) {
return a * a + b * b;
}
};
class F2 {
public:
int MemFunc(int a, int b) {
return a * a + b * b;
}
};
void main() {
F f;
f(2, 4);
F2 f2;
f2.MemFunc(2, 4);
}
6 不要重载&& || 运算符
C++重载无法实现短路规则
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
class Test
{
public:
Test(int value)
{
this->value = value;
}
int getValue()
{
cout << "value = " << this->value << endl;
return this->value;
}
Test& operator+(Test &another)
{
//Test temp(0);
cout << "执行了+重载操作符" << endl;
Test temp(this->value + another.value); //
//temp.value = this->value + another.value;
return temp;
}
//重载&&操作符
bool operator&&(Test &another)
{
cout << "执行了&&重载操作符" << endl;
if (this->value && another.value) {
return true;
}
else{
return false;
}
}
//重载||操作符
bool operator||(Test &another)
{
cout << "执行了||重载操作符" << endl;
if (this->value || another.value) {
return true;
}
else {
return false;
}
}
private:
int value;
};
int main(void)
{
int a = 10;
int b = 20;
a = 0;
//普通的&& 和||会有短路的现象
if (a && (a = 20)) //&& 如果遇见非逻辑 直接退出
{
}
cout << "a = " << a << endl;
a = 10;
if (a || (a = 20)) //&& 如果遇见是 逻辑 直接退出
{
}
cout << "a = " << a << endl;
cout << " -------- " << endl;
Test t1(0);
Test t2(20);
if (t1.getValue() && (t1 + t2).getValue() ) //普通&& 会短路现象
{
cout << "if 进入成功" << endl;
}
cout << " -------- " << endl;
if (t1 && (t1 + t2))// t1.operator&&( t1.operator+(t2) ) //我们重载的&&不会发生短路现象。
{
cout << "if 进入成功" << endl;
}
cout << " -------- " << endl;
if (t2 || (t1 + t2)) //t1.operator|| ( t1.operator+(t2) )
{
cout << "if 进入成功" << endl;
}
return 0;
}
结果
a = 0
a = 10
--------
value = 0
--------
执行了+重载操作符
执行了&&重载操作符
--------
执行了+重载操作符
执行了||重载操作符
if 进入成功
7 字符串类
要求: MyString a; MyString a(“add”); MyString b = a;
常用操作符: << >> != == > < =
MyString.h
#pragma once
#include<iostream>
using namespace std;
// c中没有字符串 字符串类(c风格)
class MyString {
friend ostream& operator<<(ostream& out, MyString& s);
friend istream& operator>>(istream& in, MyString& s);
public:
MyString(int len = 0);
MyString(const char* p);
MyString(const MyString& obj);
~MyString();
// 重载=
MyString& operator=(MyString& s);
MyString& operator=(const char* p);
// 重载[]
char& operator[](int index);
// 重载==
bool operator==(const char* p) const;
bool operator==(MyString& s) const;
// 重载!=
bool operator!=(const char* p) const;
bool operator!=(MyString& s) const;
// 重载<
int operator<(const char* p)const;
int operator<(MyString& s)const;
// 重载>
int operator>(const char* p)const;
int operator>(MyString& s)const;
// 让类指针可以在外部访问
char* c_str() {
return m_p;
}
const char* c_str2() {
return m_p;
}
int length() {
return m_len;
}
private:
int m_len;
char* m_p;
};
MyString.cpp
#define _CRT_SECURE_NO_WARNINGS
#include"MyString.h"
// 重载<<
ostream& operator<<(ostream& out, MyString& s) {
out << s.m_p;
return out;
}
// 重载>>
istream& operator>>(istream& in, MyString& s) {
in >> s.m_p;
return in;
}
MyString::MyString(int len) {
if (len == 0) {
m_len = len;
m_p = new char[m_len + 1];
strcpy(m_p, "");
}
else {
m_len = len;
m_p = new char[m_len + 1];
memset(m_p, 0, m_len);
}
}
MyString::MyString(const char* p) {
if (p == NULL) {
m_len = 0;
m_p = new char[m_len + 1];
strcpy(m_p, "");
}
else {
m_len = strlen(p);
m_p = new char[m_len + 1];
strcpy(m_p, p);
}
}
// copy 构造函数
MyString::MyString(const MyString& s) {
m_len = s.m_len;
m_p = new char[m_len + 1];
strcpy(m_p, s.m_p);
}
MyString::~MyString() {
if (m_p != NULL) {
delete[] m_p;
m_p = NULL;
m_len = 0;
}
}
MyString& MyString::operator=(MyString& s) {
// 1 释放旧内存
if (this->m_p != NULL) {
delete[] m_p;
m_len = 0;
}
// 2 根据s分配内存
m_len = s.m_len;
m_p = new char[m_len + 1];
strcpy(m_p, s.m_p);
return *this;
}
// s4 = "s22";
MyString& MyString::operator=(const char* p) {
// 1 释放旧内存
if (this->m_p != NULL) {
delete[] m_p;
m_len = 0;
}
// 2 根据p分配内存
if (p == NULL) {
m_len = 1;
m_p = new char[m_len];
strcpy(m_p, "");
}
else {
m_len = strlen(p);
m_p = new char[m_len + 1];
strcpy(m_p, p);
}
return *this;
}
// 重载[]
char& MyString::operator[](int index) {
return m_p[index];
}
// 重载==
bool MyString::operator==(const char* p) const {
if (p == NULL) {
if (m_len == 0) {
return true;
}
else {
return false;
}
}
else {
if (m_len == strlen(p)) {
return !strcmp(m_p, p);
}
else {
return false;
}
}
}
bool MyString::operator==(MyString& s) const {
if (m_len != s.m_len) {
return false;
}
return !strcmp(m_p, s.m_p);
}
// 重载!=
bool MyString::operator!=(const char* p) const {
return !(*this == p);
}
bool MyString::operator!=(MyString& s) const {
return !(*this == s);
}
// 重载<
int MyString::operator<(const char* p)const {
return strcmp(m_p, p);
}
int MyString::operator<(MyString& s)const {
return strcmp(m_p, s.m_p);
}
// 重载>
int MyString::operator>(const char* p)const {
return strcmp(p, m_p);
}
int MyString::operator>(MyString& s)const {
return strcmp(s.m_p, m_p);
}
MyString_Test.cpp
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
#include"MyString.h"
void main() {
MyString s1;
MyString s2("ccc");
MyString s2_2 = NULL;
MyString s3 = s2;
MyString s4 = "s4444";
// 运算符重载 和 重载[]
// =
s4 = s2;
s4 = "s22";
s4[0] = 'a';
cout << s4[0] << endl;
cout << s4 << endl;
if (s2 == "s2") {
cout << "=" << endl;
}
else {
cout << "!=" << endl;
}
if (s2 == s3) {
cout << "=" << endl;
}
else {
cout << "!=" << endl;
}
/*if (s3 < "bbb") { 不能直接比较,strcmp返回值a<b返回负值也会判断为真
cout << "小于" << endl;
}
else {
cout << "不等于" << endl;
}*/
int tag = (s3 < "bbb");
if (tag < 0) {
cout << "小于" << endl;
}
else if (tag > 0) {
cout << "大于" << endl;
}
else {
cout << "等于" << endl;
}
tag = (s3 < s2);
if (tag < 0) {
cout << "小于" << endl;
}
else if (tag > 0) {
cout << "大于" << endl;
}
else {
cout << "等于" << endl;
}
MyString s5("aaaaaaa");
cout << "s5:" << s5 << endl;
strcpy(s5.c_str(), "abc");
cout << "s5:" << s5 << endl;
MyString s6(128);
cout << "\n请输入字符串(回车结束)";
cin >> s6;
cout << s6 << endl;
}
结果
a
a22
!=
=
大于
等于
s5:aaaaaaa
s5:abc
请输入字符串(回车结束)13456abc
13456abc