一 运算符重载
1.1 概念
所谓重载,就是重新赋予运算符新的含义,运算符重载使得同一个运算符,具有不同的功能 运算符重载的本质就是函数的重载。
#include <iostream> using namespace std; class Complex { //friend Complex operator+(const Complex &c1,const Complex &c2); private: int a; //实部 int b; //虚部 public: Complex(int _a,int _b) { this->a = _a; this->b = _b; } void print() { cout<<a<<"+"<<b<<"i"<<endl; } Complex operator+(const Complex &c) { Complex t(0,0); t.a = this->a + c.a; t.b = this->b + c.b; return t; } }; /*Complex operator+(const Complex &c1,const Complex &c2) { Complex t(0,0); t.a = c1.a + c2.a; t.b = c1.b + c2.b; return t; }*/ int main(int argc, char const *argv[]) { Complex c1(1,2); Complex c2(2,3); Complex c(0,0); c = c1 + c2; //c = c1.operator+(c2); c.print(); return 0; }
1.2 运算符重载的规则
(1)不能重载的运算符
:: ?: . .* sizeof
(2) 重载不能改变运算符的优先级和结合性
c4 = c1 + c2 * c3; 等价于:c4 = c1 + (c2 * c3);
(3) 重载不能概念运算符的用法(即不能改变其操作数)
(4) 运算符重载不能有默认参数,否则会改变运算符的操作数
1.3 重载的步骤
1.写出函数名称。 2.根据操作数写出函数的形参。 3.根据使用场景写出函数的返回值类型。 4.完成函数体。
1.4 重载输出运算符
#include <iostream> using namespace std; class Complex { friend ostream& operator<<(ostream &out,const Complex &c); //friend Complex operator+(const Complex &c1,const Complex &c2); private: int a; //实部 int b; //虚部 public: Complex(int _a,int _b) { this->a = _a; this->b = _b; } void print() { cout<<a<<"+"<<b<<"i"<<endl; } Complex operator+(const Complex &c) { Complex t(0,0); t.a = this->a + c.a; t.b = this->b + c.b; return t; } /*ostream& operator<<(ostream &out) { out<<this->a<<"+"<<this->b<<"i"; return out; }*/ }; ostream& operator<<(ostream &out,const Complex &c) { out<<c.a<<"+"<<c.b<<"i"; return out; } int main(int argc, char const *argv[]) { Complex c1(1,2); //c1.print(); cout<<c1<<endl; //operator<<(operator<<(cout,c1),endl); return 0; }
1.5 单目运算符的重载
++ --
#include <iostream> using namespace std; class Complex { friend ostream& operator<<(ostream &out,const Complex &c); //friend Complex operator+(const Complex &c1,const Complex &c2); private: int a; //实部 int b; //虚部 public: Complex(int _a,int _b) { this->a = _a; this->b = _b; } void print() { cout<<a<<"+"<<b<<"i"<<endl; } Complex operator+(const Complex &c) { Complex t(0,0); t.a = this->a + c.a; t.b = this->b + c.b; return t; } //前置++ Complex operator++() { this->a++; this->b++; return *this; } //后置++ Complex operator++(int) //通过占位参数来构成函数重载 { Complex t = *this; this->a++; this->b++; return t; } /*ostream& operator<<(ostream &out) { out<<this->a<<"+"<<this->b<<"i"; return out; }*/ }; ostream& operator<<(ostream &out,const Complex &c) { out<<c.a<<"+"<<c.b<<"i"; return out; } int main(int argc, char const *argv[]) { Complex c1(1,2); cout<<++c1<<endl; cout<<c1++<<endl; cout<<c1<<endl; return 0; }
1.6 逻辑运算符的重载
&&: c1 && c2 ||: c1 || c2
#include <iostream> using namespace std; class Complex { friend ostream& operator<<(ostream &out,const Complex &c); //friend Complex operator+(const Complex &c1,const Complex &c2); private: int a; //实部 int b; //虚部 public: Complex(int _a,int _b) { this->a = _a; this->b = _b; } void print() { cout<<a<<"+"<<b<<"i"<<endl; } Complex operator+(const Complex &c) { Complex t(0,0); t.a = this->a + c.a; t.b = this->b + c.b; return t; } //前置++ Complex operator++() { this->a++; this->b++; return *this; } //后置++ Complex operator++(int) //通过占位参数来构成函数重载 { Complex t = *this; this->a++; this->b++; return t; } bool operator&&(const Complex &c) { } /*ostream& operator<<(ostream &out) { out<<this->a<<"+"<<this->b<<"i"; return out; }*/ }; ostream& operator<<(ostream &out,const Complex &c) { out<<c.a<<"+"<<c.b<<"i"; return out; } int main(int argc, char const *argv[]) { Complex c1(1,1); Complex c2(2,2); Complex c3(0,0); if(c1 && c2) { cout<<"成立"<<endl; } if(c3 && c1++ +c2++) //operator&&(c3,operator+(c1,c2)) //重载的时候不要重载逻辑运算符&& ||,因为违背了短路原则 { } return 0; }
1.7 数组类
#include <iostream> using namespace std; class Array { private: int size; int *data; public: Array(int s) { size = s; data = new int[size]; } int& operator[](int Index) { return data[Index]; } bool operator==(const Array &a) { /* if(this->size != a.size) { return false; } for(int i = 0; i < size;i++) { if(this->data[i] != a.data[i]) { return false; } } return true; */ return (this->data == a.data && this->size == a.size); } Array& operator=(const Array &a) { if(*this == a) { return *this; } /*if(this == &a) { return *this; }*/ this->size = a.size; delete this->data; this->data = new int[size]; for(int i = 0; i< size;i++) { this->data[i] = a.data[i]; } } ~Array() { if(data != NULL) { delete []data; } } }; int main(int argc, char const *argv[]) { Array a1(10); //创建数组对象 a1[0] = 100; for(int i = 0; i < 10;i++) { a1[i] = i + 10; } for(int i = 0; i < 10;i++) { cout<<a1[i]<<" "; } cout<<endl; Array a2(5); //a1 = a2; a1 = a1; for(int i = 0 ; i< 10;i++) { cout<<a1[i]<<" "; } cout<<endl; return 0; }
练习:自己实现string类(字符串类)
#include <iostream> #include <cstring> using namespace std; class MyString { public: MyString(); MyString(const char *str); MyString(const MyString &obj); char& operator[](int index); MyString& operator=(const char *str); MyString& operator+(const char *str); MyString& operator+(const MyString &str); bool operator==(const MyString &obj); void show(); private: char *pstring; int m_size; }; void MyString::show() { cout<<"string = "<<pstring<<endl; } MyString::MyString() { this->m_size = 0; this->pstring = NULL; } MyString::MyString(const char *str) { m_size = strlen(str) + 1; this->pstring = new char[m_size]; strcpy(this->pstring,str); } MyString::MyString(const MyString &obj) { this->m_size = obj.m_size; this->pstring = new char[m_size]; strcpy(this->pstring,obj.pstring); } char& MyString::operator[](int index) { static char ch =-1; if(index >=0 && index < this->m_size) { return this->pstring[index]; } else { printf("越界操作了\n"); return ch; } } MyString& MyString::operator=(const char *str) { this->m_size = strlen(str) + 1; if(this->pstring != NULL) { delete []this->pstring; this->pstring = new char[m_size]; } else { this->pstring = new char[m_size]; } strcpy(this->pstring,str); return *this; } MyString& MyString::operator+(const char *str) { if(this->pstring != NULL) { char *s = new char[this->m_size + 1]; strcpy(s,this->pstring); delete []this->pstring; this->pstring = new char[this->m_size + strlen(str) + 1]; stpcpy(this->pstring,s); strcat(this->pstring,str); this->m_size += strlen(str); delete []s; } else { this->pstring = new char[strlen(str) + 1]; this->m_size = strlen(str); strcpy(this->pstring,str); } return *this; } MyString& MyString::operator+(const MyString &str) { if(this->pstring != NULL) { char *s = new char[this->m_size + 1]; strcpy(s,this->pstring); delete []this->pstring; this->pstring = new char[this->m_size + str.m_size + 1]; stpcpy(this->pstring,s); strcat(this->pstring,str.pstring); this->m_size += str.m_size; delete []s; } else { this->pstring = new char[str.m_size + 1]; this->m_size = str.m_size; strcpy(this->pstring,str.pstring); } return *this; } bool MyString::operator==(const MyString &obj) { if(strcmp(this->pstring,obj.pstring) == 0) { return true; } else { return false; } } int main(int argc, char const *argv[]) { MyString m1("hello world"); m1.show(); MyString m2(m1); m2.show(); cout<<m2[3]<<endl; cout<<m2[0]<<endl; m2 = "nihao beijing"; m2.show(); MyString m3; m3 = m2 = m1; m1.show(); m2.show(); m3.show(); cout<<"***************"<<endl; MyString m4("nihao"); m4 = m4 + "helloworld"; m4.show(); MyString m5("hahahah"); m5 = m5 + m4; m5.show(); if(m5 == m4) { cout<<"m5 = m4"<<endl; } else { cout<<"m5 != m4"<<endl; } return 0; }
二 模板
泛型编程,通过建立一个通用的函数,其函数类型和形参类型不具体指定,用一个虚拟的类型来表示,这个通用的函数就是函数模板。
2.1 函数模板
template <类型形式参数表> 类型 函数名<形式参数表> { 语句块 }
#include <iostream> using namespace std; /*int add(int x,int y) //int y = 'a' { cout<<"int add(int x,int y)"<<endl; return x + y; } double add(double x,double y) { cout<<"double add(double x,double y)"<<endl; return x + y; }*/ template <typename T> T add (T x, T y) { cout<<"T add (T x, T y)"<<endl; return x + y; } template<typename T1,typename T2> void print(T1 x,T2 y) { cout<<x<<" "<<y<<endl; } int main(int argc, char const *argv[]) { cout<<add(1,2)<<endl; //隐式调用 //当模板函数和普通函数同时存在,优先调用普通函数 cout<<add<int>(1,'a')<<endl;//显示调用 //模板函数不能进行隐式类型转换 print(1,'a'); print<double,char>(1.11,'a'); return 0; }
2.2 函数模板的实现机制
实现机制:二次编译/延迟编译:第一次看到模板函数定义的位置时,编译时只检查基本语法错误,不检查数据类型的错误,使用模板函数实例化对象时,看到模板函数之后根据传递的模板实参再检查类型的错误,这种编译方法称为二次编译。
笔试题
#include <stdio.h> struct test{ int a; int b; }; void func(struct test *tt) { struct test *lt; lt = &tt[0]; printf("[0]a:%d,b: %d\n",lt->a,lt->b); lt = &tt[1]; printf("[1]a:%d,b: %d\n",lt->a,lt->b); lt = &tt[2]; printf("[2]a:%d,b: %d\n",lt->a,lt->b); } /* void func(struct test *tt,int length) { int i; struct test *lt; for(i = 0 ; i < length;i++) { lt = &tt[i]; printf("[%d]a:%d,b: %d\n",i,lt->a,lt->b); } /*printf("[0]a:%d,b: %d\n",lt->a,lt->b); lt = &tt[1]; printf("[1]a:%d,b: %d\n",lt->a,lt->b); lt = &tt[2]; printf("[2]a:%d,b: %d\n",lt->a,lt->b);*/ return; } */ int main() { struct test lm[3] = {{1,2},{11,22},{111,222}}; struct test llm = {333,444}; func(lm); func(&llm); }