Review cpp day07

Posted 达少Rising

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Review cpp day07相关的知识,希望对你有一定的参考价值。

回顾:
Review cpp day01
Review cpp day02
Review cpp day03
Review cpp day04
Review cpp day05
Review cpp day06

十九、成员指针//了解

1、成员变量指针

  • 1)定义:类型 类名::*指针变量名 = &类名::变量;
  • 2)使用
    • 对象.*成员指针变量名;
      注: ".*"称为成员指针解引用操作符
    • 对象指针->*成员指针变量名;
      注: "->*"称为间接成员指针解引用操作符

01menptr.cpp

#include <iostream>
using namespace std;

class Student{
public:
	Student(const string& name):m_name(name){}
	string m_name;
};
int main(void){
	string Student::*pname = &Student::m_name;
	Student s("张飞");
	Student* ps = new Student("赵云");
	cout << s.*pname << endl;//张飞
	cout << ps->*pname << endl;//赵云
	delete ps;
	return 0;
}

2、成员函数指针

  • 1)定义: 返回类型 (类名::*成员函数指针)(形参表) = &类名::成员函数名;
  • 2)使用
    • (对象.*成员函数指针)(实参表);
    • (对象指针->*成员函数指针)(实参表);

02menptr.cpp

#include <iostream>
using namespace std;

class Student{
public:
	Student(const string& name):m_name(name){}
	void who(void){
		cout << m_name << endl;
	}
	string m_name;
};
int main(void){
	void (Student::*pwho)(void) = &Student::who;
	Student s("张飞");
	Student* ps = new Student("赵云");
	(s.*pwho)();//张飞
	(ps->*pwho)();//赵云
	delete ps;
	return 0;
}

二十、操作符重载

eg:复数 x+yi, 实现(1+2i) + (3+4i) = 4 + 6i

1、双目操作符的重载 L#R

1.1、运算类的双目操作符:+ - …

  • 左右操作数既可以是左值也可以是右值
  • 表达式结构是右值
  • 两种实现方式:
    • 1)成员函数形式
      L#R的表达式可以被编译器翻译成L.operator#®这样成员函数调用形式,该函数的返回结果即使表达式的结果。
    • 2)全局函数形式
      L#R的表达式可以被编译器翻译成::operator#(L, R)这样全局函数调用形式,该函数的返回结果即使表达式的结果。
      注: 使用“friend”关键字,可以把一个全局函数声明为某个类的友元,友元函数可以访问类中任何成员。

03complex.cpp(第一种实现方式)

#include <iostream>
using namespace std;

class Complex{
public:
	Complex(int r, int i):m_r(r), m_i(i){}
	void print(void)const{
		cout << m_r << '+' << m_i << 'i' << endl;
	}
	//c1+c2==>c1.operator+(c2)
	/*
	*const关键字的意义:
	*1)修饰返回值,为了返回右值
	*2)常引用,为了支持常量型右操作数(右值)
	*3)常函数,为了支持常量型左操作数(左值)
	*/
	const Complex operator+(const Complex& c)const{
		Complex res(m_r+c.m_r, m_i+c.m_i);
		return res;
	}
private:
	int m_r;//实部
	int m_i;//虚部
};
int main(void){
	Complex c1(1, 2);
	Complex c2(3, 4);
	c1.print();
	c2.print();
	c1.operator+(c2);
	Complex c3 = c1 + c2;
	c3.print();//4+6i
	return 0;
}

03complex.cpp(第二种实现方式)

#include <iostream>
using namespace std;

class Complex{
public:
	Complex(int r, int i):m_r(r), m_i(i){}
	void print(void)const{
		cout << m_r << '+' << m_i << 'i' << endl;
	}
	//c1+c2==>c1.operator+(c2)
	/*
	*const关键字的意义:
	*1)修饰返回值,为了返回右值
	*2)常引用,为了支持常量型右操作数(右值)
	*3)常函数,为了支持常量型左操作数(左值)
	*/
	const Complex operator+(const Complex& c)const{
		Complex res(m_r+c.m_r, m_i+c.m_i);
		return res;
	}
private:
	int m_r;//实部
	int m_i;//虚部
	
	//友元函数可以访问类中的私有成员
	friend const Complex operator-(const Complex& l, const Complex& r);
};

const Complex operator-(const Complex& l, const Complex& r){
	Complex res(l.m_r-r.m_r, l.m_i-r.m_i);
	return res;
}

int main(void){
	Complex c1(1, 2);
	Complex c2(3, 4);
	c1.print();
	c2.print();
	c1.operator+(c2);
	Complex c3 = c1 + c2;
	c3.print();//4+6i
	
	//::operator-(c2, c1)
	c3 = c2 - ci;
	c3.print();//2+2i
	return 0;
}

1.2、赋值类的双目操作符:+= -= …

  • 左操作数必须是左值,右操作数可以是左值也可以是右值
  • 表达式的结果是左值,就是左操作数的自身。
int a = 3, b= 5;
(a +=  b) = 10;//a+=b,a=10
(a +=  5) = 10;
  • 两种实现方式:
    • 1)成员函数形式
      L # R ==》L.operator#(R)
    • 2)全局函数形式
      L # R ==》::operator#(L, R)

04complex.cpp

#include <iostream>
using namespace std;

class Complex{
public:
	Complex(int r, int i):m_r(r), m_i(i){}
	void print(void)const{
		cout << m_r << '+' << m_i << 'i' << endl;
	}
	//+=:成员函数形式
	Comple& operator+=(const Complex& c){
		m_r += c.m_r;
		m_i += c.m_i;
		return *this;
	}

	//友元函数可以把定义直接写在类的内部,但是它不属于类,本质上还是全局函数
	friend Complex& operator-=(Complex& l, const Complex& r){
		l.m_r -= r.m_r;
		l.m_i -= r.m_i;
		return l;
	}
private:
	int m_r;//实部
	int m_i;//虚部
};

int main(void){
	Complex c1(1, 2);
	Complex c2(3, 4);
	c1 += c2;//c1.operator+=(c2)
	c1.print();//4+6i

	c1 -= c2;//::operator-=(c1, c2)
	c1.print();//1+2i
	return 0;
}

2、单目操作符重载#O

2.1、计算类的单目操作符:-(取负) ~…

  • 操作数可以是左值也可以是右值
  • 表达式结果是右值
  • 两种实现方式:
    • 1)成员函数形式:
      #O ==》O.operator#();
    • 2)全局函数形式
      #O ==》::operator#(O);

05Integer.cpp

#include <iostream>
using namespace std;
class Integer{
public:
	Integer(int i=0):m_i(i){}
	void print(void)const{
		cout << m_i << endl;
	}
	//-:成员函数形式
	const Integer operator-(void)const{
		Integer res(-m_i);
		return res;
	}
	//~:全局函数形式(自定义表示乘方)
	friend const Integer operator~(const Integer& i){
		Integer res(i.m_i * i.m_i);
		return res;
	}
private:
	int m_i;
};
int main(void){
	Integer i(100);
	Integer j = -i;//i.operator-();
	j.print();//100
	j = ~i;
	j.print();//10000
	return 0;
}

2.2、自增减单目操作符:前后++、--

  • 1)前++、--
    • 操作数必须是左值;
    • 表达式结果也是左值,就是操作数的自身。
    • 两种实现方式:
      • 成员函数 #O==》O.operator#()
      • 全局函数 #O==》::operator#(O)
int a = 1;
cout << ++a << endl;//2
cout << a << endl;//2
++a = 10;//ok
cout << a << endl;//10
++++++a;//ok
cout << a << endl;//13
  • 2)后++、--
    • 操作数必须是左值;
    • 表达式结果是右值,是操作数自增减前的副本。
    • 两种实现方式:
      • 成员函数 O#==》O.operator#(哑元)
      • 全局函数 O#==》::operator#(O,哑元)
        注: 哑元只是为了区分前、后 ++, --
int a = 1;
cout << a++ << endl;//1
cout << a << endl;//2

06Integer.cpp

#include <iostream>
using namespace std;
class Integer{
public:
	Integer(int i=0):m_i(i){}
	void print(void)const{
		cout << m_i << endl;
	}
	//前++:成员函数形式
	Integer& operator++(void){
		++m_i;
		return *this;
	}
	//前--:全局函数形式
	friend Integer& operator--(Integer& i){
		--i.m_i;
		return i;
	}
	//后++:成员函数形式
	const Integer operator++(int/*哑元*/){
		Integer old = *this;
		++*this;//++m_i;
		return old;
	}
	//后--:全局函数形式
	friend const Integer operator--(Integer& i, int/*哑元*/){
		Integer old = i;
		i--;
		return old;
	}
	
private:
	int m_i;
};
int main(void){
	Integer i(100);
	Integer j = ++i;//i.operator++()
	i.print();//
	j.print();//

	j = ++++++i;
	i.print();//104
	j.print();//104

	j = --i;//::operator--(i)
	i.print();//103
	j.print();//103
	
	j = ------i;
	i.print();//100
	j.print();//100
	
	j = i++;//i.operator++(0)
	i.print();//101
	j.print();//100
	
	j = i--;//::operator--(i, 0)
	i.print();//100
	j.print();//101

	return 0;
}

3、插入和提取操作符:<< >>

  • 功能:实现自定义类型的对象的直接输入和输出
    注: 只能用全局函数形式,因为ostream cout 与 istream cin是c++的标准库中的东西,难以改变源码,所以只能用全局函数形式::operator<<(cout/cin, a);

07io_operator.cpp

#include <iostream>
ostream cout;
istream cin;

friend ostream& operator<<(ostream& os, const RIGHT& right){......}
friend istream& operator>>(istream& is, RIGHT& right){......}

cout << a << b << c;//cout<< a   cout << b << c;  cout << a   cout << b  cout << c;
cin >> a >> b >> c; 

03complex.cpp

#include <iostream>
using namespace std;

class Complex{
public:
	Complex(int r, int i):m_r(r), m_i(i){}
	friend ostream& operator<<(ostream& os, const Complex& c){
		os << c.m_r << "+" << c.m_i << "i";
		return os;
	}
	friend istream& operator>>(istream& is, Complex& c){
		is >> c.m_r >> c.m_i;
		return is;
	}
private:
	int m_r;//实部
	int m_i;//虚部

};

int main(void){
	Complex c1(1, 2);
	Complex c2(3, 4);
	//::operator << (cout, c1);
	cout << c1 << endl;
	cout << c1 << ',' << c2 << endl;
	Complex c3(0, 0);
	cout << "请输入一个复数的(实部和虚部):";
	cin >> c3;//::operator>>(cin, c3);
	cout << c3 << endl;
	return 0;
}
  • 练习:实现一个3*3矩阵,支持如下操作符重载:+ - += -(负) <<(输出)
class M33{
public:
	M33(void){
		for(int i=0; i<3; i++){
			for(int j=0; j<3; j++0){
				m_a[i][j] = 0;
			}
		}
	}
	M33(int a[][3]){
		for(int i=0; i<3; i++){
			for(int j=0; j<3; j++0){
				m_a[i][j] = a[i][j];
			}
		}
	}

private:
	int m_a[3][3];
};
int main(void){
	int a1[3][3] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
	M33 m1(a1);
	int a2[3][3] = {9, 8, 7, 6, 5, 4, 3, 2, 1};
	M33 m2(a2);
	return 0;
}

08M33.cpp

#include <iostream>
#include <iomanip>//setw(4)引用的头文件
using namespace std;

class M33{
public:
	M33(void){
		for(int i=0; i<3; i++){
			for(int j=0; jReview cpp day09

Review cpp day08

Review cpp day01

Review cpp day04

Review cpp day03

Review cpp day06