使得对象的运算像内置类型一样
a.operator+(b);
重载运算符的一些注意点:
-
不能重载运算符操作基础数据类型:(1)重载运算符必须和用户定义的class类型一起使用(2)重载的运算符的参数至少有一个应该是一个类对象(或类对象的引用)
int operator+(int x);//错误
-
编译器做对象运算会调用对象的运算符重载函数,优先调用成员方法,若无则在全局作用查找合适的运算符重载函数
双目运算符
#include <iostream>
class Complex {
public:
Complex(int r = 0, int i = 0) :real(r), img(i) {}
Complex operator+(const Complex& com) {
Complex c;
c.real = this->real + com.real;
c.img = this->img + com.img;
return c;
//return Complex(this->real+).....
//不要返回一个局部变量的指针或引用
}
int getreal()const { return real; }
private:
int real;
int img;
friend Complex operator+(const Complex& lhs, const Complex& rhs);
};
//友元函数
Complex operator+(const Complex& lhs, const Complex& rhs) {
return Complex(lhs.real+rhs.real,lhs.img+rhs.img);
}
//Complex operator+(int i,const Complex& com) {
// return Complex(i+com.getreal());
//}
int main()
{
//双目运算符:
Complex c1(1, 1);
Complex c2(2, 2);
//加法运算符的重载函数 c1.operator+(c2);
Complex c3 = c1 + c2;//需要返回一个对象
Complex c4 = c1 + 20;//若类中有一个int参数的构造函数则可以隐式转换为复数类型
//::operator+(20,c1);
Complex c4 = 20 + c1;//无法调用成员重载函数,调用全局函数
//此处的全局函数可以做三种运算
}
+=
//成员函数:
void operator+=(Complex& com){
real += com.real;
img += com.img;
}
<<运算符
对象不在左侧,所以要写成全局方法 ::operator(cout,com1);为了连续的输出,要返回ostream&
//友元:
ostream& operator<<(ostream& out, const Complex& src) {
out << "real:" << src.real << " img:" << src.img << endl;
return out;
}
istream& operator>>(istream& in, Complex& src) {
in >> src.real >> src.img;
return in;
}
string实现了关系运算符<等和[]运算符,=运算符
关系运算符
//关系运算符
bool operator>(const String& str)const {
return strcmp(m_str,str.m_str)>0;
}
bool operator<(const String& str)const {
return strcmp(m_str, str.m_str) < 0;
}
bool operator==(const String& str)const {
return strcmp(m_str, str.m_str) == 0;
}
[]运算符
将下标作为实参传入str.operator[](i)
char& operator[](int index) { return m_str[index]; }
//常对象调用下面的版本,不允许修改
const char& operator[](int index)const { return m_str[index]; }
String的实现:
#include<iostream>
//#include<string>
using namespace std;
class String {
private:
char* m_str;
public:
String(const char* str = nullptr) {
if (str != nullptr) {
m_str = new char[strlen(str) + 1];
strcpy(m_str,str);
}
else {
m_str = new char[1];
*m_str = '\0';
}
}
~String() {
delete[] m_str;
m_str = nullptr;
}
//浅拷贝有问题
//所以实现拷贝构造函数
String(const String& str) {
m_str = new char[strlen(str.m_str) + 1];
strcpy(m_str,str.m_str);
}
//赋值运算符
String& operator=(const String& src) {
if (this == &src)return *this;
delete[] m_str;
m_str = new char[strlen(src.m_str) + 1];
strcpy(m_str,src.m_str);
}
//关系运算符
bool operator>(const String& str)const {
return strcmp(m_str,str.m_str)>0;
}
bool operator<(const String& str)const {
return strcmp(m_str, str.m_str) < 0;
}
bool operator==(const String& str)const {
return strcmp(m_str, str.m_str) == 0;
}
int length() { return strlen(m_str); }
char& operator[](int index) { return m_str[index]; }
//常对象调用下面的版本,不允许修改
const char& operator[](int index)const { return m_str[index]; }
const char* c_str()const { return m_str; }
friend String operator+(const String& lhs, const String& rhs);
friend ostream& operator<<(ostream& out, const String& str);
};
String operator+(const String& lhs, const String& rhs) {
char* tmp = new char[strlen(lhs.m_str) + strlen(rhs.m_str) + 1];
strcpy(tmp,lhs.m_str);
strcat(tmp,rhs.m_str);
String t(tmp);//为了析构
delete[] tmp;
return t;
}
ostream& operator<<(ostream& out, const String& str) {
out << str.m_str;
return out;
}
这里的+运算符重载效率很低,进行了多次的空间开辟
//直接对对象底层的char*开辟空间
String operator+(const String& lhs, const String& rhs) {
//char* tmp = new char[strlen(lhs.m_str) + strlen(rhs.m_str) + 1];
String tmp;
tmp.m_str = new char[strlen(lhs.m_str) + strlen(rhs.m_str) + 1];
strcpy(tmp.m_str,lhs.m_str);
strcat(tmp.m_str,rhs.m_str);
return tmp;
}
//并非最优秀,涉及了临时对象的拷贝,构造
使用迭代器可以遍历string容器
实现String的迭代器
字符串底层成员是私有的
迭代器是容器类型的嵌套类,迭代器可以透明的访问容器内部的元素的值,无需知道底层类型(是一种统一的方式)
string::iterator it = str1.begin();//begin返回底层首元素的迭代器表示,it指向首元素
str1.ene()//表示最后一个元素的后继位置的迭代器
迭代器需要提供++运算符重载,*运算符重载
#include<iostream>
//#include<string>
using namespace std;
class String {
private:
char* m_str;
public:
String(const char* str = nullptr) {
if (str != nullptr) {
m_str = new char[strlen(str) + 1];
strcpy(m_str,str);
}
else {
m_str = new char[1];
*m_str = '\0';
}
}
~String() {
delete[] m_str;
m_str = nullptr;
}
//浅拷贝有问题
//所以实现拷贝构造函数
String(const String& str) {
m_str = new char[strlen(str.m_str) + 1];
strcpy(m_str,str.m_str);
}
//赋值运算符
String& operator=(const String& src) {
if (this == &src)return *this;
delete[] m_str;
m_str = new char[strlen(src.m_str) + 1];
strcpy(m_str,src.m_str);
}
//关系运算符
bool operator>(const String& str)const {
return strcmp(m_str,str.m_str)>0;
}
bool operator<(const String& str)const {
return strcmp(m_str, str.m_str) < 0;
}
bool operator==(const String& str)const {
return strcmp(m_str, str.m_str) == 0;
}
int length() { return strlen(m_str); }
char& operator[](int index) { return m_str[index]; }
//常对象调用下面的版本,不允许修改
const char& operator[](int index)const { return m_str[index]; }
const char* c_str()const { return m_str; }
friend String operator+(const String& lhs, const String& rhs);
friend ostream& operator<<(ostream& out, const String& str);
//迭代器
class iterator {
public:
//迭代器的底层是一个位置
iterator(char* p = nullptr):m_p(p) {
}
//两个迭代器不相等就是底层指针的不相等
bool operator!=(const iterator& it) {
return m_p != it.m_p;
}
void operator++() {
++m_p;
}
char& operator*() { return *m_p; }
private:
char* m_p;//用指针去迭代m_str
};
//返回容器底层首元素的迭代器表示
iterator begin() { return iterator(m_str); }
//返回容器底层末尾元素后继位置的迭代器表示
iterator end() { return iterator(m_str + length()); }
};
String operator+(const String& lhs, const String& rhs) {
//char* tmp = new char[strlen(lhs.m_str) + strlen(rhs.m_str) + 1];
String tmp;
tmp.m_str = new char[strlen(lhs.m_str) + strlen(rhs.m_str) + 1];
strcpy(tmp.m_str,lhs.m_str);
strcat(tmp.m_str,rhs.m_str);
return tmp;
}
ostream& operator<<(ostream& out, const String& str) {
out << str.m_str;
return out;
}
int main()
{
String str = "hello,world";
for (auto it = str.begin(); it != str.end(); ++it) {
cout<<*it<<" ";
}
}
自己实现的容器中设置了迭代器则可以使用foreach遍历容器,否则不可foreach
单目运算符
++,--运算符 单目运算符 operator++() operator(int) 为了区分前置后置,前者为前置
写为成员函数:
Complex operator++(int) {
//先返回旧值再++
Complex comp = *this;
real += 1;
img += 1;
return comp;
//return Complex().....
}
Complex& operator++() {
real += 1;
img += 1;
return *this;//非局部对象所以返回引用提高效率
}
友元和重载
class Vec2D {
public:
friend Vec2D operator+(Vec2D &firstVec, Vec2D &secondVec);
// friend double& operator[](Vec2D &v, const int &index);
// operator[] 不能重载为友元函数,只能重载为成员函数
friend Vec2D operator++(Vec2D &v);
friend Vec2D operator++(Vec2D &v, int dummy);
}
函数调用运算符(函数对象)
如果类定义了函数运算符,则此类的对象称为函数对象
一个类可以定义多个,只要它们参数类型或数量有所不同
#include<iostream>
using namespace std;
class absInt
{
public:
int operator()(int val)const {
return val<0?-val:val;
}
};
int main()
{
//调用方式:
// 将i传递给absobj.operator()
absInt absobj;
int i = -1;
int ui = absobj(i);
system("pause");
return 0;
}
vector的迭代器
实现为vector的嵌套类
template<typename T>
class Allocator
{
public:
T* allocate(size_t size)//开辟内存
{
return (T*)malloc(sizeof(T) * size);
}
void deallocate(void* p)//释放内存
{
free(p);
}
void construct(T* p, const T& val)//
{
new (p) T(val);//在指定的内存上构造(调用T的拷贝构造)
}
void destory(T* p)//对象析构
{
p->~T();
}
};
template<typename T,typename Alloc = Allocator<T>>
class Vector
{
public:
Vector(int size = 10,const Alloc& alloc = Allocator<T>())
:m_alloc(alloc)
{
//m_first = new T[size];
m_first = m_alloc.allocate(size);
m_last = m_first;
m_end = m_first + size;
}
~Vector()
{
//delete[] m_first;
for (T* p = m_first; p != m_last; ++p)
{
m_alloc.destory(p);//将有效元素析构
}
m_alloc.deallocate(m_first);//释放堆上的内存
m_first = m_last = m_end = nullptr;
}
Vector(const Vector<T>& rhs)
{
int size = rhs.m_end - rhs.m_first;
//m_first = new T[size];
m_first = m_alloc.allocate(size);
int len = rhs.m_last - rhs.m_first;
for (int i = 0; i < len; i++)
{
//m_first[i] = rhs.m_first[i];
m_alloc.construct(m_first + i, rhs.m_first[i]);
}
m_last = m_first + len;
m_end = m_first + size;
}
Vector<T>& operator=(const Vector<T>& rhs)
{
if (this == &rhs)return *this;
/*delete[] m_first;*/
for (T* p = m_first; p != m_last; ++p)
{
m_alloc.destory(p);//将有效元素析构
}
m_alloc.deallocate(m_first);//释放堆上的内存
int size = rhs.m_end - rhs.m_first;
m_first = new T[size];
int len = rhs.m_last - rhs.m_first;
for (int i = 0; i < len; i++)
{
m_first[i] = rhs.m_first[i];
}
m_last = m_first + len;
m_end = m_first + size;
return *this;
}
void push_back(const T& val)
{
if (full())expand();
//*m_last++ = val;
m_alloc.construct(m_last,val);
m_last++;
}
void pop_back()
{
if (empty())return;
--m_last;
m_alloc.destory(m_last);
}
T back()const
{
return *(m_last - 1);
}
bool full()const { return m_last == m_end; }
bool empty()const { return m_first == m_last; }
int size()const { return m_last - m_first; }
//提供使用数组下标访问
T& operator[](int index)
{
if (index < 0 || index >= size())
{
throw "OutOfRangeException";
}
return m_first[index];
}
//迭代器实现为嵌套类,所以知道vector底层的成员
class iterator
{
public:
iterator(T* ptr = nullptr)
:m_p(ptr) {}
bool operator!=(const iterator& it)const
{
return m_p != it.m_p;
}
void operator++()
{
m_p++;
}
T& operator*()
{
return *m_p;
}
const T& operator*()const
{
return *m_p;
}
private:
T* m_p;
};
iterator begin() { return iterator(m_first); }
iterator end() { return iterator(m_last); }
private:
T* m_first;
T* m_last;
T* m_end;
Allocator<T> m_alloc;
void expand()
{
int size = m_end - m_first;
//T* t = new T[2 * size];
T* t = m_alloc.allocate(2*size);
for (int i = 0; i < size; i++)
{
t[i] = m_first[i];
}
//delete[] m_first;
for (T* p = m_first; p != m_last; ++p)
{
m_alloc.destory(p);//将有效元素析构
}
m_alloc.deallocate(m_first);//释放堆上的内存
m_first = nullptr;
m_first = t;
m_last = m_first + size;
m_end = m_first + 2 * size;
}
};
测试:
int main()
{
Vector<int>vec;
for (int i = 0; i < 20; i++)
{
vec.push_back(i);
}
Vector<int>::iterator it = vec.begin();
for (; it != vec.end(); ++it)
{
cout << *it <<" ";
}
cout << endl;
return 0;
}
//输出:0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
标签:复健,const,string,int,运算符,str,operator,return,first
From: https://www.cnblogs.com/ziggystardust-pop/p/17068141.html