八十七、匿名对象
- 概念:没有名字对象
- 格式 :类名();
- 作用
- 用匿名对象给有名对象初始化的
- 用匿名对象给对象数组初始化的
- 匿名对象作为函数实参使用
示例 :
#include <iostream>
using namespace std;
class Dog
{
private:string name;string color;int *age;
public://无参构造函数Dog(){cout << "Dog::无参构造函数" << endl;}//有参构造函数Dog(string name, string c, int age):name(name),color(c),age(new int(age)){cout << "Dog::有参构造函数" << endl;}//拷贝构造函数Dog(const Dog &other):name(other.name),color(other.color),age(new int(*other.age)){cout << "Dog::拷贝构造函数" << endl;}//拷贝赋值函数Dog &operator=(const Dog &other){if(this != &other) //避免自己给自己赋值{name = other.name;color = other.color;age = new int(*other.age); //深拷贝赋值函数}cout << "Dog::拷贝赋值函数" << endl;return *this;}//析构函数~Dog(){cout << "Dog::析构函数" << endl;}
};
void fun(Dog g)//Dog g = Dog("大黄","lll",6)
{//函数代码。。。
}
int main()
{Dog d1 = Dog("大黄","lll",6); //匿名对象给有名对象初始化Dog d[3] = {Dog("大","lll",6),Dog("黄","lll",6),Dog("大黄","lll",6)};fun(Dog("大黄","lll",6)); //匿名对象作为函数实参使用return 0;
}
八十八、友元
88.1 作用
- 可以让其他一些函数或者类访问 另一个类的私有数据成员
- 友元关键字 : friend
88.2 种类
- 全局函数做友元
- 类友元
- 成员函数做友元
88.3 全局函数做友元
- 让全局函数访问一个类私有数据成员。
示例 :
#include <iostream>
using namespace std;
class Room {friend void room_friend(Room &r);
private:string keting;
public:string zoulang;Room();
};
Room::Room(){this->keting = "客厅";this->zoulang = "走廊";
}
void room_friend(Room &r){cout << "全局友元函数在访问->" << r.zoulang <<endl;cout << "全局友元函数在访问->" << r.keting <<endl;
}
int main()
{Room r1;room_friend(r1);return 0;
}
88.4 类做友元
- 一个类去访问另一个类的私有属性。
88.5 成员函数做友元
- 一个类里的成员函数去访问另一个类的私有属性。
88.6 示例
#include <iostream>
using namespace std;class Room;class Friend_Room{
private:Room *r;
public:Friend_Room();void access_room();
};class Room {
// friend class Friend_Room;friend void Friend_Room::access_room();
private:string keting;
public:string zoulang;Room();
};
Room::Room(){this->keting = "客厅";this->zoulang = "走廊";
}Friend_Room::Friend_Room(){this->r = new Room;cout << "Friend_Room 的 构造函数" << endl;
}
void Friend_Room::access_room(){cout << "Friend_Room 正在访问 " << this->r->zoulang << endl;cout << "Friend_Room 正在访问 " << this->r->keting << endl;
}int main()
{Friend_Room f_r;f_r.access_room();return 0;
}
88.7 注意
- 不要过度使用友元,会降低或者破坏封装性
- 友元不具有交互性,传递性,继承性。
八十九、const修饰的成员函数和对象(常成员函数、常对象)
- 类中所有的成员函数都可以对类中数据成员进行修改操作,
- 如果想设计一个成员函数不能对数据成员修改操作,则需要用const修饰的成员函数实现。
89.1 常成员函数
- 常成员函数 :表示该成员函数不能修改数据成员的值。
- 格式 :
返回值类型 函数名(形参列表) const {函数体内容; }
- 同名的常成员函数和非常成员函数构成重载关系,
- 原因:this指针类型不同
89.2 常对象
- 常对象表示这个对象的数据成员不能被修改。
- 格式: const 类名 对象名;
- 非常对象可以调用常成员函数,也可以调用非常成员函数,优先调用非常成员函数
- 常对象只能调用常成员函数,如果没有常成员函数,则报错
示例 :
#include <iostream>
using namespace std;class Stu
{
private:string name;int id;
public:Stu(){}Stu(string name, int id):name(name),id(id){}//常成员函数void display() const //this指针原型: Stu const * const this;{//this->name = "lisi"; 常成员函数不能对数据成员修改cout << name <<" " << id << endl;}//非常成员函数void display() //this指针原型: Stu * const this;{this->name = "lisi";cout << name <<" " << id << endl;}
};
int main()
{const Stu s1("zhangsan", 1001); //常对象s1.display(); //常对象只能调用常成员函数return 0;
}
89.3 mutable关键字
- mutable修饰成员变量,表示该成员变量可以在常成员函数中被修改 (取消常属性)
九十、运算符重载
- 概念:
运算符重载就是对运算符重新定义,赋予另一种功能,以适应不同的数据类型。 - 每种运算符重载都有两种实现方式:
- 成员函数实现运算符重载
- 全局函数实现运算符重载
90.1 算术运算符重载
种类: + - * / %
表达式: L ? R (L 左操作数 ?运算符 R右操作数)
左操作数:可以是左值,可以右值,运算过程中不可以被改变
右操作数:可以是左值,可以右值,运算过程中不可以被改变
结果:右值 (不可以被改变)
- 算术运算符重载实现方式:
-
成员函数实现运算符重载
const 类名 operator#(const 类名 &R) const {具体实现 }
第一个const 表示结果是右值 不能被改变
第二个const 表示右操作数运算过程中不能被改变
第三个const 表示左操作数运算过程中不能被改变 -
全局函数实现运算符重载
const 类名 operator#(const 类名 &L, const 类名 &R) {具体实现 }
-
示例 :
#include <iostream>
using namespace std;class Person
{friend const Person operator+(const Person &L, const Person &R);
private:int a;int b;
public:Person(){}Person(int a, int b):a(a),b(b){}//成员函数实现+号运算符重载
// const Person operator+(const Person &p) const
// {
// Person temp;
// temp.a = a + p.a;
// temp.b = b + p.b;
// return temp;
// }void show(){cout << " a = " << a << " b = " << b << endl;}
};//全局函数实现+运算符重载
const Person operator+(const Person &L, const Person &R)
{Person temp;temp.a = L.a + R.a;temp.b = L.b + R.b;return temp;
}
int main()
{Person p1(10,10);Person p2(10,10);//成员函数//简化版本//Person p3 = p1 + p2; //本质上 Person p3 = p1.operator+(p2)Person p3 = p1 + p2; //本质上 Person p3 = operator+(p1, p2)p3.show();return 0;
}
90.2 关系运算符重载
种类: > 、 >= 、 <、 <=、 ==、 !=
表达式: L ? R (L 左操作数 ?运算符 R右操作数)
左操作数:可以是左值,可以右值,运算过程中不可以被改变
右操作数:可以是左值,可以右值,运算过程中不可以被改变
结果: bool类型
- 关系运算符重载实现方式:
- 成员函数实现运算符重载
bool operator#(const 类名 &R) const {具体实现 }
- 全局函数实现运算符重载
bool operator#(const 类名 &L, const 类名 &R) {具体实现 }
- 成员函数实现运算符重载
示例 :
#include <iostream>
using namespace std;
//
class Person
{friend bool operator>(const Person &L, const Person &R);
private:int a;int b;
public:Person(){}Person(int a, int b):a(a),b(b){}//成员函数实现>号运算符重载
// bool operator>(const Person &R) const
// {
// if(a>R.a && b>R.b)
// {
// return true;
// }
// else
// {
// return false;
// }
// }void show(){cout << " a = " << a << " b = " << b << endl;}
};
//全局函数实现>号运算符重
bool operator>(const Person &L, const Person &R)
{if(L.a>R.a && L.b>R.b){return true;}else{return false;}
}
int main()
{Person p1(10,10);Person p2(10,10);if(p3 > p2) //本质上 p3.operator>(p2)//本质上 operator(p3,p2){cout <<"p3>p2" << endl;}return 0;
}
90.3 赋值运算符重载
种类: = 、+= 、 -= 、*= 、/= 、%=
表达式: L ? R (L 左操作数 ?运算符 R右操作数)
左操作数:是左值,运算过程中要被改变
右操作数:可以是左值,可以右值,运算过程中不可以被改变
结果:自身的引用
- 赋值运算符重载实现方式:
- 成员函数实现运算符重载
类名 &operator#(const 类名 &R) {具体实现 }
- 全局函数实现运算符重载
类名 &operator#(类名 &L, const 类名 &R) {具体实现 }
- 成员函数实现运算符重载
示例 :
#include <iostream>
using namespace std;class Person
{friend Person &operator+=(Person &L,const Person &R);
private:int a;int b;
public:Person(){}Person(int a, int b):a(a),b(b){}//成员函数实现+=号运算符重载
// Person &operator+=(const Person &R)
// {
// a += R.a; // a = a + R.a
// b += R.b;
// return *this;
// }void show(){cout << " a = " << a << " b = " << b << endl;}
};
//全局函数实现+=号运算符重载
Person &operator+=(Person &L,const Person &R)
{L.a += R.a; // a = a + R.aL.b += R.b;return L;
}
int main()
{Person p1(10,10);Person p2(10,10);p3+=p2; // p3 = p3 + p2 本质上 p3.operator+=(p2)p3.show();return 0;
}
小作业
- 整理代码
- 算术运算符
- 逻辑运算符
- 赋值运算符
我写的
#include <iostream>using namespace std;class Stu {//逻辑运算符重载的全局友元函数friend bool operator>(const Stu &l, const Stu &r);friend bool operator>=(const Stu &l, const Stu &r);friend bool operator<(const Stu &l, const Stu &r);friend bool operator<=(const Stu &l, const Stu &r);friend bool operator==(const Stu &l, const Stu &r);friend bool operator!=(const Stu &l, const Stu &r);//赋值运算符重载friend Stu &operator+=(Stu &l, const Stu &r);friend Stu &operator-=(Stu &l, const Stu &r);friend Stu &operator*=(Stu &l, const Stu &r);friend Stu &operator/=(Stu &l, const Stu &r);friend Stu &operator%=(Stu &l, const Stu &r);
private:double high;double weight;
public:Stu(){}Stu(double h, double w):high(h),weight(w){}void show(){cout << "high = " << this->high << endl;cout << "weight = " << this->weight << endl;puts("");}//类内实现运算符重载//算术运算符重载const Stu operator+(const Stu &s)const{Stu t;t.high = this->high + s.high;t.weight = this->weight + s.weight;return t;}const Stu operator-(const Stu &s)const{Stu t;t.high = this->high + s.high;t.weight = this->weight + s.weight;return t;}const Stu operator*(const Stu &s)const{Stu t;t.high = this->high + s.high;t.weight = this->weight + s.weight;return t;}const Stu operator/(const Stu &s)const{Stu t;t.high = this->high + s.high;t.weight = this->weight + s.weight;return t;}const Stu operator%(const Stu &s)const{Stu t;t.high = (int)this->high % (int)s.high;t.weight = (int)this->weight % (int)s.weight;return t;}//重载赋值运算符const Stu &operator=(const Stu &s){this->high = s.high;this->weight = s.weight;return *this;}
};/** 全局函数实现运算符重载* 访问类的私有属性需要添加为类的友元函数
*/
//逻辑运算符重载
bool operator>(const Stu &l, const Stu &r){if(l.high > r.high && l.weight > r.weight)return true;return false;
}
bool operator>=(const Stu &l, const Stu &r){if(l.high >= r.high && l.weight >= r.weight)return true;return false;
}
bool operator<(const Stu &l, const Stu &r){if(l.high < r.high && l.weight < r.weight)return true;return false;
}
bool operator<=(const Stu &l, const Stu &r){if(l.high <= r.high && l.weight <= r.weight)return true;return false;
}
bool operator==(const Stu &l, const Stu &r){if(l.high == r.high && l.weight == r.weight)return true;return false;
}
bool operator!=(const Stu &l, const Stu &r){if(l.high != r.high && l.weight != r.weight)return true;return false;
}//赋值运算符重载
Stu &operator+=(Stu &l, const Stu &r){l.high += r.high;l.weight += r.weight;return l;
}
Stu &operator-=(Stu &l, const Stu &r){l.high -= r.high;l.weight -= r.weight;return l;
}
Stu &operator*=(Stu &l, const Stu &r){l.high *= r.high;l.weight *= r.weight;return l;
}
Stu &operator/=(Stu &l, const Stu &r){l.high /= r.high;l.weight /= r.weight;return l;
}
Stu &operator%=(Stu &l, const Stu &r){l.high = (int)l.high % (int)r.high;l.weight = (int)l.weight % (int)r.weight;return l;
}int main()
{Stu s1(175, 60);Stu s2(170, 55);Stu s3 = s1 + s2;Stu s4 = s1 - s2;Stu s5 = s1 * s2;Stu s6 = s1 / s2;Stu s7 = s1 % s2;s1.show();s2.show();s3.show();s4.show();s5.show();s6.show();s7.show();return 0;
}