栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

【无标题】

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【无标题】

day5 class extension类的扩展 类的大小
#include
using namespace std;
class stu
{
public:
	stu()
		:a(10),b(20),c(30){}
	void dump()
	{
		cout << a << b << c << endl;
	}
private:
	int a;int b;int c;
};
int main()
{
	stu s;
	cout << sizeof(stu) << endl;cout << sizeof(s) << endl;
	return 0;
}
终端输出:
12
12

依据在 C 语言中内存对齐的知识,可以知道,此结构数据类型的大小就是 12 了。我们 发现,成员函数并不占有结构的大小。

类成员函数实际的储存方式

类成员函数只有一份(不论是类内还是类外),在对象调用过程中,传入对象的地址,具体可以表示为 this 指针

const in class 初始化列表的作用

const 修饰类数据成员必须要初始化。const初始化,一种情况在类内,另一种是初始化列表

#include
using namespace std;
class stu
{
public:   
	stu()   //推荐使用初始化列表的方式
		:a(100){}
private:
	const int a;  //const int a=100;  //直接初始化也可以
};
int main()
{
	stu s;
	return 0;
}

引用在初始化时必须要赋值

#include
using namespace std;
class stu
{
public:
	stu(int &z)
		:_z(z){}  //初始化列表是在类创建完成之前就完成的
	//stu(int& z)  //这是错误的,因为引用在初始化时要赋值
	//{
	//	_z = z;  
	//}
private:
	int& _z;
};
int main()
{
	int a = 100;
	stu s(a);
	return 0;
}
那么,在传参时可不可以写成 stu(int z),这是不可以的,如果这样写的话,传入的参数就会生成一个新的临时变量,使得int &z 的引用变成了这个临时变量的引用,而不是 a 的引用
const构成的重载
#include
using namespace std;
int add(int& a, int& b)
{
	return a + b;
}
int add (const int& a, const int& b)  //参数类型不同
{
return a + b;
}

int main()
{
	int a = 1; int b = 3;
	cout << add(a, b) << endl;
	cout << add(1, 5) << endl; //调用第二个函数,因为1 5 均为常量不能被 int& 所接受
	return 0;
}
终端输出
4
6
const构成的成员函数重载

const构成的重载函数:非const对象优先调用非const版本,const对象只能调用const版本

class A
{
public:
	A(int x, int y)
		:_x(x),_y(y)
	{}
	void foo() const
	{
		cout <<" foo() const"<< endl;
		cout << _x << _y << endl;
	}
	void foo()
	{
		cout << " foo() " << endl;
		cout << _x << _y << endl;
	}
private:
	int _x;
	int _y;2
};
int main()
{
	A a(3,2);    //非const对象
	a.foo();
	return 0;
}
终端s: foo() const
const修饰类函数
  1. const修饰类函数成员,不可以修饰全局函数
  2. const修饰函数后,承诺本函数内不会发生改变成员数据的行为,并且被const修饰的函数只能调用被const调用的函数,这保证了成员不可被更改
  3. 类外定义的const成员函数,在定义和声明处都需要const修饰符
class A
{
	void dis()const
	{函数体}
};
const修饰对象
  1. const修饰的对象其内可以有非const的数据成员,但不可修改
  2. 只能调用 const 成员函数
#include
using namespace std;
class A
{
public:
	A(int x,int y):_x(x),_y(y){}
	void dis() const
	{}
private:
	int _x;
	int _y;
};
int main()
{
	const A a(1,2);
	a.dis();
	return 0;
}
static in class

C++扩展了 static 在类中的语意,用于实现在同一个类,多个对象间数据共享,协调 行为的目的。静态变量有全局变量的优势,又不会像全变量一样被滥用。而这一类变量,即可以通 过类来管理,也可以通过类的静态函数来管理。 类的静态成员,属于类,也属于对象,但终归属于类

static data member

语法规则:

声明: static 数据类型 成员变量 【类内部】

初始化:数据类型 类名::静态数据成员 = 初值 【类外部】

调用:类名::静态数据成员 【既可以通过对象也可以通类访问】

​ 类对象.静态数据成员

//static 修饰数据成员需要初始化,不可以在类内初始化
//类外初始化,需要类名空间,且不需要static
//类的声明与实现分开的时候,初始化在 .cpp 文件中。如果初始化在 .h 文件中就会造成重定义,因为.h文件及被包含在.cpp文件中也被包含在主函数中,造成重定义
//static声明的数据成员不占对象的大小,存储在data段的 rw段。
//访问
class A
{
public:
	int _m;
	static int _share;  //相当于声明
};
int A::_share = 100;  //前面不能加static,语法规范,真正的定义
//不能写成 static int _share = 100 
int main()
{
	A a;
	cout << a._share << endl;
	cout << sizeof(a);
}
终端输出:
100
4
static的共享性,全局性优势
#include
using namespace std;
class University
{
public:
	University(string t,string l)
		:_tower(t),_lack(l){}
	static string _lib;
	void dis()
	{
		cout << _tower << " " << _lack << " " <<_lib << endl;
	}
private:
	string _tower;
	string _lack;

};
string University::_lib = "";

int main()
{
	University pk("博雅塔", "未名湖");
	University bs("电视塔", "太明湖");
	University xdf("雷峰塔", "西湖");
	pk._lib += "九阴真经";
	pk.dis();
	bs._lib += "中国挖掘机";
	bs.dis();
	xdf._lib += "英语";
	xdf.dis();
	return 0;
}
终端输出:
博雅塔 未名湖 九阴真经
电视塔 太明湖 九阴真经中国挖掘机
雷峰塔 西湖 九阴真经中国挖掘机英语

但是这样写不具有封装性,因此作修改

#include
using namespace std;
class University
{
public:
	University(string t,string l)
		:_tower(t),_lack(l){}
	static string& getLib()  //通过static函数访问
	{
		return _lib;
	}
	void dis()
	{
		cout << _tower << " " << _lack << " " <<_lib << endl;
	}
private:
	string _tower;
	string _lack;
	static string _lib;  //私有
};
string University::_lib = "";
int main()
{
	University pk("博雅塔", "未名湖");
	University bs("电视塔", "太明湖");
	University xdf("雷峰塔", "西湖");
	pk.getLib() += "九阴真经";
	pk.dis();
	bs.getLib() += "中国挖掘机";
	bs.dis();
	xdf.getLib() += "英语";
	xdf.dis();
	return 0;
}
访问

类的静态成员即属于类也属于对象,但终归是属于类

#include
using namespace std;
class A
{
public:
	int _m;
	static int _share;
};
int A::_share = 100;
int main()
{
	A a;
	cout << A::_share;  //没有对象是可以通过命名空间的形式访问,说明_share属于类
	cout << a._share< 

在创建对象前,类的静态成员对象就已经完成了初始化并存放在data段

static修饰函数
  1. 目的是为了管理静态变量
  2. 在类内声明在类外定义(初始化),声明要加static定义不加static
  3. 静态成员函数只能访问静态的成员(数据成员和函数成员),不能访问非静态的成员,下面解释原因:
class A
{
public:
	static void manageA();
	static void manageB(){}
	void foo(){}
private:
	static int a;
};
int A::a = 100;
void manageA()
{
}
int main()
{
	A a;
	a.manageA(); a.manageB;
	A::manageA();A::manageB();
	return 0;
}

在调用函数foo时,函数为了可以找到所要操作的对象会传入this指针。调用manageA()manageB()函数时,既可以使用对象也可以使用类来调用(本质都是使用类来调用),使用类调用是不用传入this指针的。静态成员函数中没有this指针,那么就没有资格访问非静态成员。非静态函数可以访问静态成员。静态成员函数只能访问静态数据成员。原因:非静态成员函数在调用时this指针被当作参数传进。而静态成员函数属于类,而不属于对象,没有this指针

排号的实现
#include
using namespace std;
class Server
{
public:
	Server(char n)
		:_serverName(n){}
	void serverOne()
	{
		if (_openFlag && _lastServerIdx < _turnCount)
		{
			_lastServerIdx++;
			cout << "server " << _serverName << "server for " << _lastServerIdx << endl;
			if (_lastServerIdx >= _turnCount)
				_openFlag = false;
		}
	}
	static bool stillOpen()
	{
		return _openFlag;
	}
	static int& getTurn()
	{
		return _turnCount;
	}
private:
	char _serverName;
	static int _turnCount;
	static bool _openFlag;
	static int _lastServerIdx;
};
int Server::_turnCount = 0;
bool Server::_openFlag = true;
int Server::_lastServerIdx = 0;

int main()
{
	Server a('A'), b('B');
	cout << "how many pople in the row" << endl;
	int num;
	cin >> num;
	for (int i = 0; i < num; i++)
	{
		cout << "idx = "<< ++Server::getTurn() << endl;
	}
	do
	{
		a.serverOne(); b.serverOne();
	} while (Server::stillOpen());
	return 0;
}
课堂实战 单例模式

一个类仅有一个实例的现像,称为单例模式

#include
using namespace std;
class singleton
{
public:
	static singleton* getsingleton()  //在类中自己创建
	{
		if (ptr == nullptr)
		{
			singleton* ptr = new singleton;
			return ptr;
		}
	}
	static void freesingleton()  //调用函数销毁
	{
		if (ptr != nullptr)
		{
			delete ptr;
			ptr = nullptr;
		}
	}
private:
	singleton(){}
	~singleton(){}
	singleton(const singleton& another){}
	singleton& operator=(const singleton& another){}
	static singleton* ptr;
};
singleton* ptr = nullptr;
static const
class A
{
public:
	A(){}
	void dis()
	{
		cout << arr << endl;
	}
private:
	static const int arr = 100;  //只有这一种初始化的方式
};
point to class member

C++拓展了指针在类中的使用,使其可以只想类成员(数据成员和函数成员),这种行为是类层面的而不是对象层面的

#include
using namespace std;

class Student
{
public:
	Student(string n,int nu):name(n),num(nu){}
private:
	string name;
	int num;
};
int main()
{
	Student s("zhangsan", 100);
	Student* ps = &s;  //
	//string* psn = &s.name;  这不可以,因为此行为破坏了封装,name不可访问
	//下面要将的指针是指向类层面的指针,而不是指向对象

	return 0;
}
语法:

指向非静态数据成员的指针在定义时必须和类相关联,在使用时必须和具体的对象关 联。 由于类不是运行时存在的对象。因此,在使用这类指针时,需要首先指定类的一个对 象,然后,通过对象来引用指针所指向的成员。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uyMkSHhz-1655359987346)(E:博客photoSnipaste_2022-05-17_15-59-18.png)]

#include
using namespace std;
class Student
{
public:
	Student(string n,int nu):name(n),num(nu){}
	void dis()
	{
		cout << name << endl;
	}
	string name;
	int num;
};
int main()
{
	Student s("zhangsan", 100);//通过对象访问
	Student* ps = &s;          //通过指向对象的指针访问
	string Student::* psn = &Student::name;
	//定义指向类成员的指针
	cout << s.*psn << endl;
	cout << ps->*psn << endl;
	void(Student:: * pdis)() = &Student::dis;
	//定义指向类函数的指针变量,此函数不能是静态函数
	(s.*pdis)();      //在类对象中通过类指针调用函数
	(ps->*pdis)();    
	return 0;
}
终端输出:
zhangsan
zhangsan
zhangsan
zhangsan
应用

统一接口:

#include
using namespace std;

struct Point
{
	int add(int x, int y)
	{
		return x + y;
	}
	int sub(int x, int y)
	{
		return x - y;
	}
	int mul(int x, int y)
	{
		return x * y;
	}
	int div(int x, int y)
	{
		return x % y;
	}
};
int oper(Point* pf, int (Point::* fd)(int, int), int x, int y)
{
	return (pf->*fd)(x, y);
}
typedef int(Point::* PF)(int, int);
//给类型 int (Point::*)(int , int)起别名PF
int main()
{
	Point*s = new Point;
	PF pf = &Point::add;
	cout< 

更加隐蔽的接口:

#include
using namespace std;
class Game
{
public:
	Game()
	{
		pf[0] = &Game::a;	pf[1] = &Game::b;
		pf[2] = &Game::c;	pf[3] = &Game::d;
	}
	void select(int i)
	{
		(this->*pf[i])(i);
	}
private:
	void a(int idx) { cout << "idx = " << idx << endl; }
	void b(int idx) { cout << "idx = " << idx << endl; }
	void c(int idx) { cout << "idx = " << idx << endl; }
	void d(int idx) { cout << "idx = " << idx << endl; }
	enum num{n = 4};
	void(Game::*pf[n])(int idx);
};
int main()
{
	Game game;
	game.select(2);	game.select(0);
}
本质:

指向类成员的指针,具有指针的形而不具体指针的实质,或者,确切意义上说,不指 是指针,而存放的是偏移量

指向类静态成员的指针

语法:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rsFhwZOu-1655359987348)(E:博客photoSnipaste_2022-05-19_10-44-28.png)]

#include 
using namespace std;
#include 
using namespace std;
class A
{
public:
static void dis();
static int data;
};
void A::dis()
{
cout< 
day6 
friend有元 
引入: 
#include
using namespace std;
class sprite
{
public:
	int getlifeCount()
	{
		cout << lifeCount << endl;
	}
	void setlifeCount(int lb)
	{
		lifeCount = lb;
	}
private:
	int lifeCount;
};
void fight(sprite& fd)   //全局函数
{
	fd.setlifeCount(fd.getlifeCount() - 20);
	cout << fd.getlifeCount();
}
int main()
{
	sprite a;
	fight(a);
}

每次打精灵的时候都要大量调用getlifeCount函数和setlifeCount函数,这耗费了大量的压栈和出栈,效率低,如果fight函数可以直接操作对象中的私有成员就避免了多次调用set,get函数的开销,因此引入了友元函数,相当于类对外界的一个授权,授权访问私有成员的权限

#include
using namespace std;
class sprite
{
	friend void fight(sprite& fd);  //变为友元函数
public:
	int getlifeCount()
	{
		cout << lifeCount << endl;
	}
	void setlifeCount(int lb)
	{
		lifeCount = lb;
	}
private:
	int lifeCount;
};
void fight(sprite& fd)
{
	fd.lifeCount -= 20;   //友元函数直接操作私有成员
	cout << fd.getlifeCount();
}
int main()
{
	sprite a;
	fight(a);
}
why 有元

采用类的机制后实现了数据的隐藏与封装,类的数据成员一般定义为私有成员,成员 函数一般定义为公有的,依此提供类与外界间的通信接口。 但是,有时需要定义一些函数,这些函数不是类的一部分,但又需要频繁地访问类的 数据成员,这时可以将这些函数定义为该类的友元函数。除了友元函数外,还有友元类, 两者统称为友元。 友元的作用是提高了程序的运行效率(即减少了类型和安全性检查及调用的时间开销), 但它破坏了类的封装性和隐藏性,使得非成员函数可以访问类的私有成员。 友元可以是一个函数,该函数被称为友元函数;友元也可以是一个类,该类被称为友 元类

声明为谁的有元就可以通过谁的对象访问谁的私有成员

友元函数: 全局函数作友元
#include
#include
using namespace std;
class Point
{
	friend double getDistance(Point& p1, Point& p2); //位置并不重要
public:
	Point(int x = 0,int y = 0):_x(x),_y(y){}
	void dumpFormate()
	{
		cout << _x << "  " << _y << endl;
	}
private:
	double _x;
	double _y;
};
double  getDistance(Point& p1, Point& p2)
{
	double dx = p1._x - p2._x;
	double dy = p1._y - p2._y;
	return sqrt(dx * dx + dy * dy);
}
int main()
{
	int a = 2; double b = 2.3;
	Point p1(3, 4);
	Point p2(7, 8);
	cout << getDistance(p1,p2)<< endl;
	return 0;
}
类函数作友元

引入:

class Point
{
	friend double managePoint::getDistance(Point& p1, Point& p2);   //添加友元
public:
	Point(int x = 0,int y = 0):_x(x),_y(y){}
	void dumpFormate()
	{
		cout << _x << "  " << _y << endl;
	}
private:
	double _x;
	double _y;
};
class managePoint
{
public:
	double  getDistance(Point& p1, Point& p2);          //声明
};
double  managePoint::getDistance(Point& p1, Point& p2)  //定义
{
	double dx = p1._x - p2._x;
	double dy = p1._y - p2._y;
	return sqrt(dx * dx + dy * dy);
}

编译错误:这里在添加友元函数时用到了managePoint::getDistance这个类函数,但是前面并没有定义这个类,更没有这个类函数

调转这两个类之后:

class managePoint
{
public:
	double  getDistance(Point& p1, Point& p2);          //声明
};
class Point
{
	friend double managePoint::getDistance(Point& p1, Point& p2);   //添加友元
public:
	Point(int x = 0,int y = 0):_x(x),_y(y){}
	void dumpFormate()
	{
		cout << _x << "  " << _y << endl;
	}
private:
	double _x;
	double _y;
};
double  managePoint::getDistance(Point& p1, Point& p2)  //定义
{
	double dx = p1._x - p2._x;
	double dy = p1._y - p2._y;
	return sqrt(dx * dx + dy * dy);
}

在类managePoint中用到了 Point& 这属于类Point在managePoint之后,这就要用到前项声明了

前项声明:

  1. 不能定义对象
  2. 可以用于定义指向这个类型的指针或引用
  3. 用于声明(不是定义),作为形参类型或者函数的返回值类型

结果:

#include
#include
using namespace std;
class Point;                 //前项声明
class managePoint
{
public:
	double  getDistance(Point& p1, Point& p2);          //声明
};
class Point
{
	friend double managePoint::getDistance(Point& p1, Point& p2);   //添加友元
public:
	Point(int x = 0,int y = 0):_x(x),_y(y){}
	void dumpFormate()
	{
		cout << _x << "  " << _y << endl;
	}
private:
	double _x;
	double _y;
};
double  managePoint::getDistance(Point& p1, Point& p2)  //定义
{
	double dx = p1._x - p2._x;
	double dy = p1._y - p2._y;
	return sqrt(dx * dx + dy * dy);
}
int main()
{
	int a = 2; double b = 2.3;
	Point p1(3, 4);
	Point p2(7, 8);
	managePoint ss;
	cout < 
友元类 

当希望一个类中所有成员函数均变为另一个类的私有成员时,可以将该类声明为另一类的友元类

声明
class A
{
	friend class B;
	public:     ...
	private:    ...
};

例子1:

#include
#include
using namespace std;
class Point
{
	friend class managePoint;   
	//添加友元类,相当于对类mamagePOoint授权,使得类managePoint可以访问类Point的私有成员
public:
	Point(int x = 0, int y = 0) :_x(x), _y(y) {}
	void dumpFormate()
	{
		cout << _x << "  " << _y << endl;
	}
private:
	double _x;
	double _y;
};

class managePoint
{
public:
	double getDistance(Point& p1, Point& p2)  //定义
	{
		double dx = p1._x - p2._x;
		double dy = p1._y - p2._y;
		return sqrt(dx * dx + dy * dy);
	}
};

int main()
{
	int a = 2; double b = 2.3;
	Point p1(3, 4);
	Point p2(7, 8);
	managePoint ss;
	cout << ss.getDistance(p1, p2) << endl;
	return 0;
}

若将两个类互换位置,则编译错误,因为类managePoint中用到了类Point但类Point还没有定义也没有授权

例子2

#include
#include
using namespace std;
class Point
{
	friend class managePoint;
public:
	Point(int x,int y):x_(x),y_(y){}
private:
	float x_;
	float y_;
};

class managePoint
{
public:
	float getDistancd(Point& p1, Point& p2);
	float getArea(Point& p1, Point& p2, Point& p3);
};
float managePoint::getDistancd(Point& p1, Point& p2)
{
	float dx = p1.x_ - p2.x_;
	float dy = p1.y_ - p2.y_;
	return sqrt(dx * dx + dy * dy);
}
float managePoint::getArea(Point& p1, Point& p2, Point& p3)
{
	float d1 = getDistancd(p1, p2);
	float d2 = getDistancd(p1, p3);
	float d3 = getDistancd(p2, p3);
	float p = (d1 + d3 + d2);
	return sqrt(p * (p - d1)*(p - d2)*(p - d3));
}
int main()
{
	Point p1(2, 5);
	Point p2(8, 3);
	Point p3(12, 56);
	managePoint ms;
	cout< 

注意:

  • 友元不可继承
  • 友元关系是单向的
  • 友元关系不具有传递性
运算符重载

运算符重载的本质是函数重载。函数名即:operator + 符号

友元重载
#include
using namespace std;
class complex
{
	friend complex operator+(complex& c1, complex& c2);
public:
	complex(float r = 0,float i = 0):real_(r),image_(i){}
	void dump()
	{
		cout << real_ << " ( " << image_ << " ) " << endl;
	}
private:
	float real_;
	float image_;
};
complex operator+(complex&c1,complex&c2)
{
	complex ret;
	ret.real_ = c1.real_ + c2.real_;
	ret.image_ = c1.image_ + c2.image_;
	return ret;
}
int main()
{
	complex a(1, 2); complex b(3.4);
	complex sum = a + b;
	sum.dump();
	return 0;
}
成员重载
#include
using namespace std;

class complex
{
	
public:
	complex(float r = 0,float i = 0):real_(r),image_(i){}
	void dump()
	{
		cout << real_ << " ( " << image_ << " ) " << endl;
	}
	complex operator+(complex&another)
	//此函数不可返回引用。函数返回值是会产生一个临时对象,而返回引用不会,既然是引用,那马就要考虑引用谁,如果引用的是函数内栈	  //上创建的东西,那么当函数结束时此栈就会消失,自然不能做返回。这里在函数内新建了一个类对象,存在栈上显然不能返回引用
	{
		complex ret;
		ret.real_ = this->real_ + another.real_;
		ret.image_ = this->image_ + another.image_;
		return ret;
	}
	complex& operator=(complex&another)
	{
		this->real_ = another.real_;
		this->image_ = another.image_;
		return *this;
	}
private:
	float real_;
	float image_;
};

int main()
{
	complex a(1, 2); complex b(3,4);
	complex sum = a.operator+(b);  // a + b,  this指针的值为类对象a的地址
	sum.dump();  
	return 0;
}

对上面的代码进行优化

class complex
{
public:
	complex(float r = 0,float i = 0):real_(r),image_(i){}
	void dump()
	{
		cout << real_ << " ( " << image_ << " ) " << endl;
	}
	const complex operator+(const complex&another)
	//此函数不可返回引用。函数返回值是会产生一个临时对象,而返回引用不会,既然是引用,那马就要考虑引用谁,如果引用的是函数内栈	  //上创建的东西,那么当函数结束时此栈就会消失,自然不能做返回。这里在函数内新建了一个类对象,存在栈上显然不能返回引用
	{
		complex ret;
		ret.real_ = this->real_ + another.real_;
		ret.image_ = this->image_ + another.image_;
		return ret;
	}
	complex& operator=(const complex &another)
	{
		this->real_ = another.real_;
		this->image_ = another.image_;
		return *this;
	}
private:
	float real_;
	float image_;
};

首先·对两对象传入的参数加上了const,因为两函数并没有改变传入对象的成员。又对 complex operator+(const complex&another) 前加了const表示,返回值不可更改,下面解释原因/

	int a = 2, b = 3, c = 4;
	a = b = c;
	a + b + c;
	(a + b) = c;  //不可以
	a = (b + c);

为了使对象和普通变量拥有一样的性质,让(a+b) = c无法通过,于是就在类函数operator+前加了const,使他不可被赋值

双目运算符重载的研究方法以 +=为例
先有
int main()
{
	int a=10,b=20,c=30
	a+=b;b+=c;
	cout <<"a:"image_ += another.image_;
	}
private:
	float real_;
	float image_;
};

先有:
int main()
{
	int a = 10, b = 20, c = 30;
	a += b += c;      //将b+=c的返回值做参数
	cout <<  "a:" << a << " b:" << b << " c:" << c << endl;
}
#include
using namespace std;

class complex
{
public:
	complex(int r = 0,int i = 0):real_(r),image_(i){}
	complex operator+=(const complex& another)
	{
		this->real_ += another.real_;
		this->image_ += another.image_;
		return *this;
	}
	void dump()
	{
		cout << real_ << " " << image_;
	}
private:
	float real_;
	float image_;
};

int main()
{
	int a = 10, b = 20, c = 30;
		a += b += c;
	cout <<  "a:" << a << " b:" << b << " c:" << c << endl;
	complex aa(10, 0), bb(20, 0), cc(30, 0);
	aa += bb += cc;
	//相当于aa.operator+=(bb.operator+=(cc)),将bb.operator+=(cc)的返回值作为参数传入
	//第一次重载函数完成后生成了临时对象并没有实际的内存,对临时对象的引用为常引用const
	aa.dump();
	bb.dump();
	cc.dump();
}


先有:
int main()
{
	int a = 10, b = 20, c = 30;
	(a += b) += c;
	cout <<  "a:" << a << " b:" << b << " c:" << c << endl;
}
后有:
complex& operator+=(const complex& another)
//返回引用,若不返回引用:先完成(a + b)返回一个临时对象,之后再临时对象上加c ,之后临时对象销毁这样a上只加了b而没有加c
	{
		this->real_ += another.real_;
		this->image_ += another.image_;
		return *this;
	}
单目运算符的研究方式以 - 为例
先有:
int main()
{
	int n = 5;
	cout << -n << endl;cout << n << endl;
}
后有:
class complex
{
public:
	complex(int r = 0,int i = 0):real_(r),image_(i){}
	complex operator-()
	{
		return complex(-real_, -image_);
	}
	void dump()
	{
		cout << real_ << " " << image_;
	}
private:
	float real_;
	float image_;
};
先有:
int n = 10;
-n = 5;     //error。说明不可被赋值
再有:
const complex operator-()
{
	return complex(-real_, -image_);
}
先有:
cout<<-(-n)< 
单目运算符 ++ 重载 
先有:
int main()
{
	int a = 10;
	cout << ++a < 
流输入输出运算符重载 
#include 
using namespace std;
class Complex
{
public:
Complex(float x=0, float y=0):_x(x),_y(y){}
friend ostream & operator<<(ostream &os, const Complex & c);
friend istream & operator>>(istream &is, Complex &c);
//成员的话必须保证左值为该类的对象
private:
float _x;
float _y;
};
ostream & operator<<(ostream &os, const Complex & c)
{
os<<"("<>(istream &is, Complex &c)
{
is>>c._x>>c._y;
return is;
}
int main()
{
Complex c(2,3);
cout<>c;
cout< 

也可以写为:

#include 
using namespace std;
class Complex
{
public:
Complex(float x=0, float y=0):_x(x),_y(y){}
friend ostream & operator<<(ostream &os, const Complex & c)
{
os<<"("<>(istream &is, Complex &c)
{
is>>c._x>>c._y;
return is;
}
//成员的话必须保证左值为该类的对象
private:
float _x;
float _y;
};
int main()
{
Complex c(2,3);
cout<>c;
cout< 
user-Defined Type Cast 自定义类型强转 
自定义类型转化构造函数 
语法: 
class 目标类
{
	m(const 原类型 & 源对象的引用)
	{
		更具需求完成转换
	}
}
目标:实现其他类型到本类型的额转化
原理:转换构造函数。是只有一个参数的构造函数,如有多个参数,只能称为构造函数,而不是转换函数。转换构造强调是一转一
例子:
#include 
using namespace std;
class print2D
{
	friend class print3D;
public:
	print2D(int x = 0,int y = 0):x_(x),y_(y){}
private:
	int x_;
	int y_;
};
class print3D
{
public:
	print3D(int x = 0, int y = 0, int z = 0) :x_(x), y_(y),z_(z) {}
	//转化构造函数的本质也是构造函数
	print3D(const print2D & d2)
	{
		this->x_ = d2.x_;
		this->y_ = d2.y_;
		this->z_ = rand() % 100;
	}
	void dumpFormate()
	{
		cout << "x: " << x_ << "y: " << y_ << "z: " << z_;
	}
private:
	int x_;
	int y_;
	int z_;
};

print3D convid(const print2D& d2)
{
	//print3D d3(d2);
	//return d3;
	return print3D(d2);
	//这样会返回一个无名的类对象
}

int main()
{
	print2D d2(10,100);
	print3D d3;
	//d3 = d2;   //第一种转化方式,相当于d3(d2)
	d3 = convid(d2);     用有名的类对象接收无名的类对象
	d3.dumpFormate();
	return 0;
}
explicit (显性)关键字

用于修饰构造函数

#include 
using namespace std;
class print2D
{
	friend class print3D;
public:
	print2D(int x = 0, int y = 0) :x_(x), y_(y) {}
private:
	int x_;
	int y_;
};
class print3D
{
public:
	print3D(int x = 0, int y = 0, int z = 0) :x_(x), y_(y), z_(z) {}
	explicit print3D(const print2D& d2)
	{
		this->x_ = d2.x_;
		this->y_ = d2.y_;
		this->z_ = rand() % 100;
	}
	void dumpFormate()
	{
		cout << "x: " << x_ << "y: " << y_ << "z: " << z_;
	}
private:
	int x_;
	int y_;
	int z_;
};
int main()
{
	print2D d2(10, 100);
	//print3D d3;
	//d3(d2)  //显示调用可以编过
	// d3 = d2  //不行,编不过
	print3D d3 = static_cast(d2);   //必须加强转,因为构造函数被声明为explicit(显性的)
	
	d3.dumpFormate();
	return 0;
}
操作符函数转化 语法:
class 源类
{
	operator 目标类(void)
	{
		return 目标类构造器(源类实参)
	}
}
例子:
#include 
#include 
using namespace std;
class print3D
{
public:
	print3D(int x = 0, int y = 0, int z = 0) :x_(x), y_(y), z_(z) {}
	void dumpFormate()
	{
		cout << "x: " << x_ << "y: " << y_ << "z: " << z_;
	}
private:
	int x_;
	int y_;
	int z_;
};
class print2D
{
public:
	print2D(int x = 0, int y = 0) :x_(x), y_(y) {}
	operator print3D()
	{
		return print3D(this->x_, this->y_,rand() % 100);  //相当于执行print3D的构造函数,后返回
	}
private:
	int x_;
	int y_;
};
print3D convert(print2D& d2)
{
	return print3D(d2); 
}

int main()
{
	print2D d2(10, 0);
	print3D d3(d2);     //3种由d2 转换为 d3的方法
	print3D d3 = d2;
	d3 = convert(d2);
	d3.dumpFormate();
	return 0;
}
operator作类的转换函数
  1. 转换函数必须是类方法
  2. 转换函数不能指定返回类型
  3. 转换函数不能有参数
operator 目标类(void)
{
	return 目标类构造器(源类实参)  //其实是调用了目标类的构造器
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/977089.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号