目录
一:友元函数
优势:友元函数可以访问类中的所有成员(公有,私有,保护),提高程序的运行效率
关键字:friend
缺点:破坏面向对象程序设计类的封装性
示例如下:
CStaff.h:
#ifndef CSTAFF_H
#define CSTAFF_H
class Staff
{
public:
Staff();
Staff(int id,char *name,char *pwd,int prole);
~Staff();
static int num;//静态数据成员 放在公有的
static int getNum();
//友元函数---类外函数
//破坏封装性 尽量少用
friend void printStaffInfo(Staff &staff);
private:
int ID;
char name[20];
char pwd[20];
int role;
protected:
};
#endif
CStaff.cpp:
#include"CStaff.h"
#include<iostream>
using namespace std;
//不存在对象当中 是所有对象都能够公共访问的
//独立于对象 存在在类当中的
int Staff::num = 1000;//静态成员的初始化
Staff::Staff()
{
Staff::num++;
}
Staff::Staff(int id,char *name,char *pwd,int prole)
{
this->ID = id;
strcpy(this->name,name);
strcpy(this->pwd,pwd);
this->role = prole;
Staff::num++;
}
Staff::~Staff()
{
}
main.cpp:
#include<iostream>
using namespace std;
#include"CStaff.h"
//友元函数访问员工类的数据成员
void printStaffInfo(Staff &staff)
{
cout<<"id = "<<staff.ID<<endl;
cout<<"name = "<<staff.name<<endl;
cout<<"pwd = "<<staff.pwd<<endl;
cout<<"role = "<<staff.role<<endl;
}
int main()
{
//在类外部定义一个函数:打印用户信息
Staff s1(1001,"admin","123456",1);
printStaffInfo(s1);
//id = 1001
//name = admin
//pwd = 123456
//role = 1
}
二:友元类
如窗口基类 访问 控件基类 (在控件基类中 写入 窗口基类的友元)
friend class CWinBase; //类的声明 可以通过友元类(访问类外) 但破坏封装性了
int CWinBase::WinRun()
{
int i=0,key=0;
for(i=0;i<this->ctrlCount;i++)
{
if(this->ctrlArr[i]->ctrlType==EDIT||this->ctrlArr[i]->ctrlType==BUTTON)
{
CTools::gotoxy(this->ctrlArr[i]->startX+2,this->ctrlArr[i]->startY+1);
break;
}
}
}
使用友元类,就可以不用写get方法,但是却会破坏面向对象程序设计的封装性,因此最好还是写get方法提供类外访问的接口
三:运算符重载
以复数为例,示例如下
CComplex.h:
#ifndef CCOMPLEX_H
#define CCOMPLEX_H
class CComplex
{
public:
CComplex();//构造
CComplex(int a,int b);//带参
~CComplex();//析构
void print();
CComplex operator+(CComplex &complex); //隐式传参 this指针 a+b
CComplex operator++(int); //int作为区分 后置++ i++
CComplex& operator++(); // 前置++ ++i
friend CComplex operator*(CComplex &c1,CComplex &c2);
protected:
private:
int real; //实部
int imag; //虚部
};
#endif
CComplex.cpp:
#include"CComplex.h"
#include<iostream>
using namespace std;
CComplex::CComplex()//构造
{
this->real = 10;
this->imag = 20;
}
CComplex::CComplex(int a,int b)//带参
{
this->real = a;
this->imag = b;
}
CComplex::~CComplex()
{
}
CComplex CComplex::operator+(CComplex &complex)//双面运算符+
{
CComplex tmp;
//this 指针
tmp.real = this->real + complex.real;
tmp.imag = this->imag + complex.imag;
return tmp;
}
void CComplex::print()
{
cout<<this->real<<"+"<<this->imag<<"j"<<endl;
//1+2j + 3+4j = 4+4j
}
CComplex CComplex::operator++(int)//单目后置++
{
//先使用值 再自增
CComplex tmp;
tmp.real = this->real;
tmp.imag = this->imag;
this->real++;
this->imag++;
return tmp;
}
CComplex& CComplex::operator++()//单目前置++
{
this->real++;
this->imag++;
return *this;
}
main.cpp:
a. 类成员函数实现双目运算符+的重载
#include<iostream>
using namespace std;
#include"CComplex.h"
int main()
{
CComplex c1,c3;
CComplex c2(1,2);
//类成员函数实现 双目运算符+的重载
c3 = c1 + c2;
c3.print();//11+22j
}
b. 类成员函数实现单目运算符重载 i++ 单目后置++
#include<iostream>
using namespace std;
#include"CComplex.h"
int main()
{
CComplex c1,c3;
CComplex c2(1,2);
//类成员函数实现单目运算符重载 i++
//先打印 在自增
(c1++).print(); //10+20j
c1.print(); //11+21j
}
c. 类成员函数实现单目运算符重载 ++i 单目前置++
#include<iostream>
using namespace std;
#include"CComplex.h"
int main()
{
CComplex c1,c3;
CComplex c2(1,2);
//类成员函数实现单目运算符重载 ++i 前置++
//先自增 再打印
(++c1).print(); //11+21j
c1.print(); //11+21j
}
d. 单目后置++ 显式调用
#include<iostream>
using namespace std;
#include"CComplex.h"
int main()
{
// CComplex c1;
CComplex c2(1,2);
(c2.operator ++(0)).print(); //1+2j
c2.print(); //2+3j
}
e. 单目前置++ 显式调用
#include<iostream>
using namespace std;
#include"CComplex.h"
int main()
{
CComplex c1;
// CComplex c2(1,2);
(c1.operator++()).print(); //11+21j
c1.print(); //11+21j
}
f. 类的友元函数实现运算符*重载 【实部*实部 虚部*虚部】
#include<iostream>
using namespace std;
#include"CComplex.h"
//类的友元函数实现运算符*重载 实部*实部 虚部*虚部
CComplex operator*(CComplex &c1,CComplex &c2)
{
CComplex tmp;
tmp.real = c1.real * c2.real;
tmp.imag = c1.imag * c2.imag;
return tmp;
}
int main()
{
CComplex c1,c3;
CComplex c2(1,2);
//类成员函数实现 双目运算符*的重载
c3 = c1 * c2;
c3.print(); //10+40j
}
四:= 运算符重载
调用拷贝构造函数的情况:
1. 通过一个已经存在的对象去创造一个新的对象 此时会调用这个新对象的拷贝构造函数
2. 当一个对象作为函数实参传入时 此时会调用形参的拷贝构造函数
3. 当函数的返回值是一个对象时 此时接收这个函数返回值的对象会调用拷贝构造函数
从上面的情况 可以总结出:
当一个已经构造好了的对象去赋值给一个还未构造的对象,此时就会调用这个还未构造的对象的拷贝构造函数 产生的结果就是会有新的对象产生
CComplex c4 = c1;
= 运算符重载 示例如下
CComplex.h:
#ifndef CCOMPLEX_H
#define CCOMPLEX_H
class CComplex
{
public:
CComplex();
CComplex(int a,int b,char* word);
void print();
~CComplex();
CComplex operator+(CComplex &complex); //双面+
CComplex operator++(int); //单目后置++
CComplex& operator++(); //单目前置++
friend CComplex operator*(CComplex &c1,CComplex &c2);//类的友元函数实现运算符*重载
CComplex& operator = (CComplex &c1); //=运算符重载
protected:
private:
int real; //实部
int imag; //虚部
char *p; //字符串
};
#endif
CComplex.cpp:
#include"CComplex.h"
#include<iostream>
using namespace std;
#include<stdlib.h>
CComplex::CComplex()
{
this->real = 10;
this->imag = 20;
this->p = new char[20];//开空间
memset(p,0,20);//初始化
}
CComplex::CComplex(int a,int b,char* word)
{
this->real = a;
this->imag = b;
this->p = new char[20];//开空间
memset(p,0,20);//初始化
strcpy(p,word);//赋值
}
CComplex CComplex::operator+(CComplex &complex)//双面+
{
CComplex tmp;
//this 指针
tmp.real = this->real + complex.real;
tmp.imag = this->imag + complex.imag;
return tmp;
}
void CComplex::print()
{
cout<<this->real<<"+"<<this->imag<<"j"<<endl;
//1+2j + 3+4j = 4+4j
cout<<this->p<<endl;
}
CComplex CComplex::operator++(int)//单目后置++
{
//先使用值 再自增
CComplex tmp;
tmp.real = this->real;
tmp.imag = this->imag;
this->real++;
this->imag++;
return tmp;
}
CComplex& CComplex::operator++() //单目前置++
{
this->real++;
this->imag++;
return *this;
}
CComplex::~CComplex()
{
}
CComplex& CComplex::operator = (CComplex &c1)//= 运算符重载
{
this->real = c1.real;
this->imag = c1.imag;
this->p = new char[20];//开空间
memset(p,0,20);//初始化
strcpy(p,c1.p);//赋值
return *this; //引用返回值
}
main.cpp:
#include<iostream>
using namespace std;
#include"CComplex.h"
int main()
{
//实现 =运算符 的重载
CComplex c1;
CComplex c2(1,2,"hello");
//两个对象都是已经创建好了的
c1 = c2;
c1.print();//1+2j hello
}
对于拷贝构造函数 和 = 运算符重载 ,做好区分:
= 运算符重载:两个对象都是已经创建好了的
拷贝构造函数: 一个已经构造好了的对象去赋值给一个还未构造的对象