目录
重载算术运算符(加减乘除 )
重载加号运算符的形式为:
class Object
{
public:
Object operator + (const Object& other)
{}
};
重载类内操作符
程序功能:实现分数的加号操作。
#include "pch.h"
#include <iostream>
#include <stdio.h>
class Fraction
{
public:
Fraction() : num(1), den(1)
{}
Fraction(int n, int d) : num(n), den(d)
{}
Fraction operator + (const Fraction& other)
{
Fraction result;
result.den = den * other.den;
result.num = num * other.den + den * other.num;
return result;
}
private:
int num;//分子
int den;//分母
};
int main()
{
Fraction fa(2, 3);
Fraction fb(3, 5);
Fraction fc = fa + fb;
return 0;
}
注意:
(1)重载操作符的形式上像一个函数,但它不是函数;
(2)名称:operator +, 这个是固定不变的
(3)返回值:类型不变,总是为该对象的类型
(4)参数:基本上不变
(5)受public/protected/private的限制
重载全局操作符
#include "pch.h"
#include <iostream>
#include <stdio.h>
class Fraction
{
public:
Fraction() : num(1), den(1)
{}
Fraction(int n, int d) : num(n), den(d)
{}
public: //这里被声明为public不然operator +不能访问num和den
int num;//分子
int den;//分母
};
Fraction operator + (const Fraction& a, const Fraction& b)
{
Fraction result;
result.den = a.den * b.den;
result.num = a.num * b.den + a.den * b.num;
return result;
}
int main()
{
Fraction fa(2, 3);
Fraction fb(3, 5);
Fraction fc = fa + fb;
return 0;
}
上面强制将num和den变成了public,但是一般情况下我们都会申明为private。那如果申命为private时,就需要使用friend修饰符。具体实现如下所示:
#include "pch.h"
#include <iostream>
#include <stdio.h>
class Fraction
{
friend Fraction operator +(const Fraction& a, const Fraction& b);
public:
Fraction() : num(1), den(1)
{}
Fraction(int n, int d) : num(n), den(d)
{}
private:
int num;//分子
int den;//分母
};
Fraction operator + (const Fraction& a, const Fraction& b)
{
Fraction result;
result.den = a.den * b.den;
result.num = a.num * b.den + a.den * b.num;
return result;
}
int main()
{
Fraction fa(2, 3);
Fraction fb(3, 5);
Fraction fc = fa + fb;
return 0;
}
重载元素操作符[]
重载元素操作符[]的一般形式
Element& operator [] (Type Index){}
其中,
(1)名字:operator [],是固定不变的
(2)返回值:一般应该返回一个子元素的引用,表示返回值是一个“左值”,可读可写
(3)参数:类型可以自己选择,用于指定元素的下标,不一定要使用int,使用其他类型也可以,比如char*。
[]用于访问一组元素中的一个元素。默认地,数组是支持下标访问的。
例如:
int a[5] = {1,2,3,4,5};
a[0] = 10;
int b = a[0];
当一个对象设计用于包含多个元素时,可以重载操作符[]
比如,一个字符串Text,它包含了多个元素(每个元素时一个字符)
Text txt("hello,world");
char ch = txt[0];
又比如,一个DataStore里存储了多个Student数据
DataStore ds;
Student& st = ds["nick"];
程序功能:可以使用下标访问字符串元素,并修改字符串元素。
class Text
{
public:
Text(const char* str)
{
m_size = strlen(str) + 1;
m_buf = new char[m_size];
strcpy(m_buf, str);
}
~Text()
{
delete[] m_buf;
}
char& operator[] (int index)
{
return m_buf[index];
}
private:
int m_size;
char* m_buf;
};
int main()
{
Text m_text("hello");
char a = m_text[0];
m_text[0] = 'H';
return 0;
}
程序功能:用链表实现学生数据的插入,并可通过下标来访问某个学生。
DataStore.h
#ifndef _DATASTORE_H
#define _DATASTORE_H
struct Student
{
int id;
char name[16];
Student* next;
};
class DataStore
{
public:
DataStore();
~DataStore();
Student& operator [](const char* name);
void Add(const Student* data);
Student* Find(int id);
void Print();
public:
static Student null_one; //这里是为了防止返回无效值而设置的一个特定值
private:
Student m_head;
};
#endif // !_DATASTORE_H
DataStore.cpp
#include "pch.h"
#include "DataStore.h"
#include <stdlib.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
static Student null_one = {-1, "null"};
DataStore::DataStore()
{
m_head.next = {0};
}
DataStore::~DataStore()
{
Student* p = m_head.next;
while (p)
{
Student* next = p->next;
free(p);
p = next;
}
}
void DataStore::Add(const Student* data)
{
Student* copy = (Student*)malloc(sizeof(Student));
*copy = *data;
Student* cur = m_head.next;
Student* pre = &m_head;
while (cur)
{
if (copy->id < cur->id)
{
break;
}
pre = cur;
cur = cur->next;
}
copy->next = pre->next; //obj->next = cur;
pre->next = copy;
}
Student* DataStore::Find(int id)
{
Student* p = m_head.next;
while (p)
{
if (p->id == id)
return p;
p = p->next;
}
return null_one;
}
void DataStore::Print()
{
Student* p = m_head.next;
while (p)
{
printf("id:%d, name:%s\n", p->id, p->name);
p = p->next;
}
}
Student& DataStore::operator [](const char* name)
{
Student* p = m_head.next;
while (p)
{
if (strcmp(p->name, name) == 0)
{
return *p;
}
p = p->next;
}
return null_one;
}
main.cpp
#include "pch.h"
#include <iostream>
#include <stdio.h>
#include "DataStore.h"
int main()
{
DataStore ds;
Student s1 = {1, "nick"};
ds.Add(&s1);
Student s2 = { 2, "nancy" };
ds.Add(&s2);
ds.Print();
Student stu = ds["nick"];
if (stu.id > 0)
{
printf("This Object has been found.");
}
return 0;
}
注意:
(1)操作符[]的返回值类型为引用,才算是符合使用习惯;(毕竟又是需要作为左值而存在)
(2)元素下标的类型是不一定要用int,用char*也可以;
(3)操作符[]是可以重载的,参数类型不同;
(4)必须考虑元素不存在的情形。(就如上面代码的static Student null_one = {-1, "null"};)
重载关系操作符
关系操作符:> < >= <= == !=
比如下面代码就直接报错,因为自定义的类并没有实现==操作。
Fraction fa(2, 3);
Fraction fb(4, 6);
if(fa == fb) //编译报错
{
}
一般有2种写法:
(1)重载类操作符
class Object
{
public:
bool operator == (const Object& other) {}
};
a. 名称operator ==
b. 返回值:bool
c. 参数:可以重载
(2)重载全局操作符
bool operator == (const Object& a, const Object& b) {}
接下来以重载类操作符为例
程序功能:实现分数==功能。
#include "stdafx.h"
#include "stdio.h"
#include <stdlib.h>
#include <string.h>
class Fraction
{
public:
Fraction() : num(1), den(1)
{}
Fraction(int n, int d) : num(n), den(d)
{}
bool operator == (const Fraction& other)
{
if (num * other.den == den * other.num)
return true;
return false;
}
public:
int num;
int den;
};
int main()
{
Fraction a(2, 3);
Fraction b(4, 6);
if (a == b)
{
printf("OK.");
}
return 0;
}
结果为:
OK.
重载转换操作符()
一般形式:
class Object
{
public:
operator Type() //Type目标类型
{
Type result;
return result;
}
};
C++允许将一个类型转换成另一个类型。比如int a = (int) 1.23; //将double转成int类型
小括号就是类型转换符,括号里的就是要转换的目标类型。
就比如上面按个分数的例子,我们可以使用()将其转换成double类型的数据。
Fraction fa(4,5);
double value = (double)fa;
但这个需要自己重写()操作符,以实现类型转换的操作。
#include "stdafx.h"
#include "stdio.h"
#include <stdlib.h>
#include <string.h>
class Fraction
{
public:
Fraction() : num(1), den(1)
{}
Fraction(int n, int d) : num(n), den(d)
{}
operator double()
{
return (double)num/den; //先将num转成double,然后结果就被自动转成double
}
public:
int num;
int den;
};
int main()
{
Fraction a(2, 3);
double c = (double)a;
return 0;
}
重载输入输出操作符
C++中引入操作符 >> 表示输入,<< 表示输出
注意:在位操作符里他们承担的意思是:左移位,右移位。
在位操作中:
unsigned int a = 0xAA << 4; //左操作数为整形时,表示位移
输入输出:
Logger lg;
lg << "hello, world"; //左操作数为自定义对象,表示输入输出
一般形式:
Logger& operator << (Type value)
{
return *this;
}
(1)名称:operator <<
(2)返回值:左值,一般返回对象自己
(3)参数:待输出的数据
程序功能:定义一个类logger,用于输出打印日志
#include "stdafx.h"
#include <stdio.h>
class Point
{
public:
Point(int x, int y)
{
this->x = x;
this->y = y;
}
public:
int x, y;
};
class Logger
{
public:
Logger& operator << (int value)
{
printf("%d", value);
return *this;
}
Logger& operator << (double value)
{
printf("%f", value);
return *this;
}
Logger& operator << (const char* value)
{
printf("%s", value);
return *this;
}
Logger& operator << (const Point& point)
{
printf("(%d,%d)", point.x, point.y);
return *this;
}
};
int main()
{
Logger lg;
Point p(1, 2);
lg << 1 << " hello";
lg << p;
return 0;
}
为什么返回左值?
习惯而已。所以只能返回引用。