一、友元(函数和类)
1.友元函数:在类内申明,在类外定义,不属于当前类,但可以访问当前类的所有成员变量和成 员 方法(包含私有共有和保护)
2.定义: friend 返回值 函数名(类的对象)
在函数前加friend。
3.调用:不可以通过成员.函数名() 的方式调用,因为不是成员函数。
当做全局函数使用,直接函数名加参数的方式使用;
4.注意:申明在类内,加上friend,一般情况下需要传入当前类的对象
可以在类内实现,也可以在类外实现,类外实现不需要加friend关键字
5.友元类:把另外一个类放入当前类,则另外一个类可以访问我的所有成员变量和成员函数。
格式: class test { friend class 类名; }
6.注意:友元类不是相互的,当a是b的友元时,a可以通过b的对象访问b中的所有成员函数和变量,包含私有。但b不可以访问a的私有和包含成员变量。
代码:
头文件:
- #ifndef FRIEND_H
- #define FRIEND_H
- class stu
- {
- private:
- int age;
- public:
- friend void print(stu &dd);//友元函数
- stu(int k1);//有参构造
- stu();//无参构造
- ~stu();//析构函数
- };
-
-
-
-
- #endif // FRIEND_H
.cpp文件:
- #include <iostream>
- #include"friend.h"
- using namespace std;
-
- void print(stu &dd)
- {
- cout<<"age: "<<dd.age<<endl;
- }
- stu::stu(int k1)
- {
- age=k1;
- }
- stu::stu()
- {
- age=10;
- }
- stu::~stu()
- {
- cout<<"析构了"<<endl;
- }
-
- int main()
- {
- stu danny(100);
- stu danny1;
- print(danny);
- print(danny1);
-
- return 0;
- }
二、类的静态成员
分为类的静态成员函数和类的静态成员变量
2.1静态成员变量:
格式:static 类型 变量;
注意:静态成员变量直接属于类,不属于对象。只有一份。所有对象公用一份,如果通过某一个对象修改静态成员变量,所有对象都修改。
2.2 静态成员变量初始化
初始化在类外,使用 类型 类名::变量名 = 值的方式进行初始化
例如: class Box{public: static double lenght;}
2.3使用
类名::静态变量名= 值;
对象.静态变量名 = 值;(不属于对象)
2.4静态成员函数
格式: static 返回值 函数名(参数列表){}
注意:静态成员函数在没有对象的时候也可以访问,直接使用类名::函数名的方式,不一定要对象.静态成员函数 的形式
静态成员函数智能访问静态成员数据、其他静态成员函数和类外的其他函数,不可以访问非静态成员变量
可以使用静态成员函数来判断类的其他对象是否创建。
静态成员函数中无this指针,所以不可以访问普通成员变量。
如果声明和实现分开,在实现函数时不需要加static
代码:
头文件:
- #ifndef POINTER_H
- #define POINTER_H
- #include
- using namespace std;
-
- class pointer
- {
- private:
-
- double lenght;
- double width;
- double heighr;
- public:
- static int num;//静态成员变量需要在类内声明,类外初始化
- pointer();
- ~pointer();
- pointer(double a,double b,double c);
- static void show();//静态函数 只能调用类里面的静态变量 , 不能调用其他成员
- };
-
- #endif // POINTER_H
.cpp 文件
- #include "pointer.h"
-
- pointer::pointer()
- {
- num++;
- lenght=0;
- width=0;
- heighr=0;
- }
-
- pointer::~pointer()
- {
-
-
- }
- pointer::pointer(double a,double b,double c)
- {
- num++;
- lenght=a;
- width=b;
- heighr=c;
-
- }
-
- int pointer::num=0;//静态成员变量需要在类内声明,类外初始化
- void pointer::show()
- {
- cout<<"lenght:"<<num<<endl;
- }
-
-
- int main()
- {
-
-
- pointer a;
- pointer b(1.1,2.2,3.3);
- a.show();
- b.show();
-
-
-
- return 0;
- }
-
-
-
-
三、this
初始化列表: 是在构造函数时候,对成员变量进行初始化使用
格式:在构造函数后加冒号,后加成员变量名(参数)的形式
例如:class box { int a;int b;int c; public: box(int a,int b,int c):a(a),b(b),c(c){ } };
注意: 初始化列表在构造函数执行前执行,执行完后再执行大括号中内容。
this指针:在类中表示当前对象。理解成"我". 每个对象的我都表示自己。
每个对象都有一个特殊的指针,指向对象本身;
在每一个普通成员函数中,都默认传入了this指针,所以成员函数才能使用成员变量
而在普通成员函数中使用成员变量时,可以省略this。所以成员变量当成了普通变量使用。
注意:静态成员函数没有this指针。友元函数也没有this指针。
代码:
头文件:
- #ifndef KK_H
- #define KK_H
- #include
- using namespace std;
-
- class kk
- {
- private:
- int a;
- int b;
- int c;
- public:
- kk();
- kk(int a,int b,int c);
- void print();
- void hh()const;
-
- };
-
- #endif // KK_H
.cpp 文件
- #include "kk.h"
-
- kk::kk():a(0),b(0),c(0)//初始化,成员数据,在括号里面的程序运行之前//在初始化构造之前的时候 已经把数据给赋值了
- {
-
- }
- kk::kk(int a,int b,int c)
- {
- this->a=a;//this 指针指向自己的对象成员
- this->b=b;
- this->c=c;
- }
- void kk::print()
- {
- cout<<a<<" "<<b<<" "<<c<<endl;
-
- }
- void kk::hh()const//定义之前加了 const 所以成员不可以被改变
- {
- cout<<"a:"<<a<<endl;
-
- }
-
- int main()
- {
-
-
- kk dd;
- kk cc(1,2,3);
- dd.print();
- cc.print();
-
-
-
- return 0;
- }
四、const成员
分类:const成员变量 和 const成员函数
const成员变量:
特点:
不允许修改
必须在类内部初始化,可以在定义成员变量时赋值;
可以在初始化列表中对const成员变量初始化。不可以在构造函数的大括号中直接赋值const变量
const成员函数:
定义:const关键字必须放在参数列表后,函数的声明和实现都必须带const属性
注意: 在const成员函数中,不允许修改成员变量的值
const成员函数中,不可以调用非const的成员函数。
const的对象只可以调用const的成员函数,不可以调用非const成员函数
非const的对象可以调用const成员函数和非const成员函数
const成员函数和非const成员函数构成重载(重点)
代码:
头文件:
- #ifndef PERSON_H
- #define PERSON_H
- #include
- #include
- using namespace std;
- class person
- {
- private:
- int age;
- const string name = "abc";
- public:
- person();
- void grow();
- void show()const;
-
- };
-
- #endif // PERSON_H
.cpp文件
- #include "person.h"
-
- person::person():age(0)
- {
-
- }
- void person::grow()
- {
- cout<<"age: "<<age<<" "<<"name :"<<name<<endl;
-
- }
- void person::show()const
- {
- cout<<"age: "<<age<<" "<<"name :"<<name<<endl;
- }
-
- int main()
- {
-
-
- person a;
- a.show();
- a.grow();
-
-
-
- return 0;
- }
五、运算符重载:
1. 重载:在相同作用域内函数名相同参数列表不同(const),返回值没关系。
2.运算符重载:重新编写一个运算符,用来对多个对象进行操作,例如 student a;student b; a+b;
3.格式:返回值 operator运算符(参数){ }
4.运算符:
算数运算符: + - * / %
关系运算符: > < >= <= == !=
逻辑运算符: && || !
位运算符: & | ^ >> <<
自增自减: ++x , x++ , --x , x--;
赋值运算符: = , += >>=
单目运算符: +(正号) -(负号) &(地址)
内存申请: new delete sizeof
其他: ( ) -> , [ ] , ?:
不可以重载的运算符:?: . (点) sizeof , *(解引用运算符) ::(域运算符) #
6.运算符重载的实现方式:
成员函数实现:在类内做运算符重载,一般情况下传入一个对象或者一个变量
赋值运算符 =, 下标运算符[ ], 指针运算符,流运算符 >>
全局函数实现:在类外定义,一般情况下参数是两个对象(双目运算符)
7.算数运算符:
成员变量实现方式: int operator + (const person& other) { int x = this->age + other.age; return x; }
友元函数实现方式: friend person operator -(const person& me,const person& other){ return person(me.age+other.age);}
全局函数实现方式: int operator -(const person& me,const person& other){return me.getAge()+other.getAge();}
补充:匿名对象,没有变量名的对象,用完后立马析构,构建对象形式类似 调用构造函数;
8.关系运算符重载
成员变量实现方式: bool operator > (const person& other) { }
代码:
头文件
- #ifndef CHONGZAI1_H
- #define CHONGZAI1_H
- #include<iostream>
- #include<string>
- using namespace std;
- class chongzai1
- {
- private:
- int age;
- public:
- chongzai1(int age =2);
- void show();
- int get();
- void set(int age1);
- int get_age()const;
- chongzai1 operator+(const chongzai1& a);//重载 加法+
- //友元不是类的成员
- friend bool operator <=(const chongzai1 & me,const chongzai1 &other);//友元方式实现 <= 的运算符重载
- //重载 符号
- chongzai1 operator -();
- };
-
- chongzai1 operator -(chongzai1& me , chongzai1& other );//重载 运算符减号
- chongzai1 operator /(const chongzai1& me ,const chongzai1& other );//重载 运算符 除号
- chongzai1 operator *(const chongzai1& me ,const chongzai1& other );//重载 运算符 乘号
- chongzai1 operator --(chongzai1 & me,int);//重载 后减减
- chongzai1 operator ++(chongzai1 & me);//重载 前加加
- chongzai1 operator ++(chongzai1 & me,int);//重载 后加加
- chongzai1 operator --(chongzai1 & me);//重载 前减减
-
-
- #endif // CHONGZAI1_H
.cpp 文件
- #include "chongzai1.h"
-
- chongzai1::chongzai1(int age)//默认值,实现的时候不用加
- {
- this->age=age;
- }
-
- void chongzai1::show()
- {
- cout<<"age:"<<age<<endl;
- }
-
- int chongzai1::get()
- {
- return age;
- }
- void chongzai1::set(int age1)
- {
- age=age1;
- }
-
- int chongzai1::get_age()const
- {
- return age;
- }
-
- chongzai1 chongzai1::operator +(const chongzai1& a)
- {
- chongzai1 x;
- x.age= a.age+this->age;
- return x;
- }
-
- chongzai1 operator -(chongzai1& me ,chongzai1& other )
- {
- int x = me.get()+other.get();
- return chongzai1(x);//临时对象 匿名对象
- }
-
- chongzai1 operator /(const chongzai1& me , const chongzai1& other )
- {
- int x = me.get_age()/other.get_age();
- return chongzai1(x);//临时对象 匿名对象
- }
-
- chongzai1 operator *(const chongzai1& me , const chongzai1& other )
- {
- int x = me.get_age()* other.get_age();
- return chongzai1(x);//临时对象 匿名对象
- }
-
- bool operator <=(const chongzai1 & me,const chongzai1 &other)
- {
- return me.get_age()<=other.get_age();
- }
- //后减减
- chongzai1 operator--( chongzai1 & me,int)
- {
- chongzai1 temp =me;
- int x=me.get()-1;
- me.set(x);
- return temp;
- }
-
- //前加加
- chongzai1 operator ++(chongzai1 & me)//前加加
- {
-
- int x=me.get()+1;
- me.set(x);
- return me;
- }
-
- chongzai1 operator ++(chongzai1 & me,int)//后加加
- {
- chongzai1 temp =me;
- int x=me.get_age()+1;
- me.set(x);
- return temp;
- }
-
- chongzai1 operator --(chongzai1 & me)//前减减
- {
- int x=me.get()-1;
- me.set(x);
- return me;
- }
- chongzai1 chongzai1::operator -()//重载 负号
- {
- return chongzai1(-age);
- }
-
- int main()
- {
-
- /*
- chongzai1 c=a+b;
- a.show();
- b.show();
- c.show();
- chongzai1 d =a/b;
- d.show();
- chongzai1 dd=a*b;
- dd.show();
-
- cout.setf(ios_base::boolalpha);//bool 类型输出 ture 和 false 不是输出 1 或者 0
- bool jj=b<=a;
- cout<<jj<<endl;
- */
- --b;
- b.show();
- ++a;
- a.show();
-
- chongzai1 c= b--;
- chongzai1 d= a++;
- b.show();
- c.show();
- a.show();
- d.show();
-
- d=-d;
- d.show();
-
- return 0;
- }
-
>> 运算符号的重载
头文件
- #ifndef LIU_H
- #define LIU_H
- #include "liu.h"
- #include
- #include
- #include
- #include
- using namespace std;
-
- class liu
- {
- public:
- int id;
- string name, grade;
- liu(){};
- liu(int id, string name, string grade);
- bool operator < (const liu & s) const;
- };
-
- istream & operator >> (istream & in, liu & s);
- ostream & operator << (ostream & out, liu & s);
-
- #endif // LIU_H
.cpp 文件
- #include "liu.h"
- #include <iostream>
- #include <vector>
- #include <string>
- #include <algorithm>
- using namespace std;
- bool liu ::operator < (const liu & s) const
- {
- return id<s.id;
- }
-
- istream & operator >> (istream & in, liu & s)
- {
- in >> s.id >> s.name >> s.grade;
- return in;
- }
-
- ostream & operator << (ostream & out, liu &s)
- {
- out << s.id << " " << s.name << " " << s.grade << endl;
- return out;
- }
- /*
- int main()
- {
- vector<Student> sv;
- liu temp;
- while (cin >> temp)
- {
- sv.push_back(temp);
- }
- sort(sv.begin(), sv.end());
- for (int i = 0; i < sv.size(); ++i)
- cout << sv[i];
- return 0;
- }
- */