1、友元概念:
1、打破了C++的封装性(运算符重载也会)
2、声明友元的关键字是friend,friend只会出现在声明除
3、友元函数不是类的成员,不带this指针,友元函数可以访问对象任意成员属性,包括私有属性
2、全局函数称为友元:
#include <iostream>
using namespace std;
class room
{
friend void getroom(room &room1);
private:
string bedroom;
public:
string livingroom;
};
void getroom(room &room1)
{
cout<<room1.bedroom<<endl;
cout<<room1.livingroom<<endl;
}
void test04()
{
room room1;
getroom(room1);
}
int main(int argc, char *argv[])
{
test04();
return 0;
}
3、成员函数作为友元:
class Room; //向前声明Room类,但并不知道类内部的成员
//作为友元类的定义,必须定义在最上方(友元类就是包含成员函数的类)
//友元类的成员函数必须在所有类的最下方定义
class GoodGay
{
private:
public:
GoodGay()
{
}
void visitroom01(Room & room);
void visitroom02(Room & room);
};
class Room
{
// friend void GoodGay::visitroom01(Room &room);
friend void GoodGay::visitroom02(Room &room); ///< 友元只能出现在声明处
private:
string bedroom;
public:
Room(string bed, string living)
{
bedroom = bed;
livingroom = living;
}
string livingroom;
};
void GoodGay::visitroom01(Room & room)
{
//cout << "访问" << room.bedroom << endl;
cout << "访问" << room.livingroom << endl;
}
void GoodGay::visitroom02(Room & room)
{
cout << "访问" << room.bedroom << endl;
cout << "访问" << room.livingroom << endl;
}
void test01()
{
Room room("卧室", "客厅");
GoodGay gay;
gay.visitroom01(room);
gay.visitroom02(room);
}
4、类作为友元函数:
#include <iostream>
using namespace std;
class Room; //向前声明Room类,但并不知道类内部的成员
//作为友元类的定义,必须定义在最上方(友元类就是包含成员函数的类)
//友元类的成员函数必须在所有类的最下方定义
class GoodGay
{
private:
public:
GoodGay()
{
}
void visitroom01(Room & room);
void visitroom02(Room & room);
};
class Room
{
friend class GoodGay;
//直接友元类
private:
string bedroom;
public:
Room(string bed, string living)
{
bedroom = bed;
livingroom = living;
}
string livingroom;
};
void GoodGay::visitroom01(Room & room)
{
cout << "访问" << room.bedroom << endl;
cout << "访问" << room.livingroom << endl;
}
void GoodGay::visitroom02(Room & room)
{
cout << "访问" << room.bedroom << endl;
cout << "访问" << room.livingroom << endl;
}
void test01()
{
Room room("卧室", "客厅");
GoodGay gay;
gay.visitroom01(room);
gay.visitroom02(room);
}
int main(int argc, char *argv[])
{
test01();
return 0;
}
友元函数注意:
1、友元关系不能继承
2、友元关系是单向的,类A是类B的朋友,但类B不一定是A的朋友。
3、友元关系不具备传递性。类B是类A的朋友,类C是类B的朋友,但类A不一定是类C的朋友。
例1:电视机类的实现(电视机有开机和关机状态,有音量,有频道,提供音量操作的方法,频道操作的方法。 由于电视机只能逐一调整频道,不能指定频道)
//第一步分析类中的成员函数和成员变量
//成员变量电视状态,音量,频道,成员函数有音量操作,频道操作,开关操作。
#include <iostream>
using namespace std;
class tv
{ enum
{
minchannel = 1,
maxchannel = 100
//枚举出电视频道。
};
enum
{
minvoice = 0,
maxvoice = 100
//枚举出电视音量。
};
private:
bool state;
//电视只有俩种状态,开,关
int voice;
int channel;
public:
tv()
{
state = false;
voice = minvoice;
channel = minchannel;
//电视的初始状态。
}
tv(bool state,int voice,int channal)
{
//初始化开机状态
this->state = state;
this->voice = voice;
this->channel = channal;
}
tv(const tv &ob)
{
this->state = ob.state;
this->voice = ob.voice;
this->channel = ob.channel;
}
void onoff();//显示开关机状态
void setvoice();//显示音量状态
void setchannel();//显示频道状态
};
void test01()
{
tv tv1(true,101,101);
//调用有参构造,打开电视机,设置三个不同的状态
tv1.onoff();
tv1.setvoice();
tv1.setchannel();
}
void tv::onoff()
{
bool b =(state? true:false);
cout<<"the state of tv is"<<" "<<b<<endl;
//电视是开会输出1,关输出0
}
void tv::setvoice()
{
if((this->voice) >= minvoice && (this->voice) <= maxvoice)
{
cout<<"现在的音量是"<<this->voice<<endl;
}
if((this->voice) >maxvoice)
{
cout<<"voice is max"<<endl;
return;
}
this->voice++;
}
void tv::setchannel()
{
if(this->channel >= minchannel && this->channel <= maxchannel)
{
cout<<"现在的频道是"<<this->channel<<endl;
}
this->channel++;
if(this->channel > maxchannel+1)
{
this->channel = minchannel;
cout<<"现在的频道是"<<this->channel<<endl;
return;
}
}
int main(int argc, char *argv[])
{
test01();
return 0;
}
例2:实现遥控器对电视的控制(遥控器类的实现)
//第一步分析类中的成员函数和成员变量
//成员变量电视状态,音量,频道,成员函数有音量操作,频道操作,开关操作。
#include <iostream>
using namespace std;
class tv;
class remote
//遥控器类
{
private:
tv *p1;
//遥控器中声明一个tv中的指针,方便传入电视的数据
public:
remote(tv*tv1)
//接收传入的tv指针
{
p1 =tv1;
//初始化
}
void onof(tv*p1);
void setvoice(tv*p1);
void setchannel(tv*p1);
//上面三个函数方便调用tv的状态
void setchannelnum(tv*p1,int num);
//遥控器可以改变tv的频道
};
class tv
{
friend class remote;
enum{minchannel = 1,maxchannel = 100};
enum{minvoice = 0,maxvoice = 100};
private:
bool state;
int voice;
int channel;
public:
tv()
{
//tv的初始状态
state = false;
voice = minvoice;
channel = minchannel;
}
tv(bool on,int voice,int channel)
{
//实例化只会的状态
this->state = on;
this->voice = voice;
this->channel =channel;
}
tv(const tv&ob)
{
//有指针要拷贝构造
this->state = ob.state;
this->voice = ob.voice;
this->channel = ob.channel;
}
void onof();
void setvoice();
void setchannel();
//tv自己的三个状态函数
};
void test01()
{
tv tv1(true,40,3);
//实例化后开机的状态
tv1.onof();
tv1.setchannel();
tv1.setvoice();
//上面三个函数可以表现出tv的三个状态
remote remote1(&tv1);
//实例化一个遥控器类,传入tv的指针初始化
remote1.onof(&tv1);
remote1.setchannelnum(&tv1,20);
//改变tv的频道
remote1.setchannel(&tv1);
remote1.setvoice(&tv1);
//显示出遥控器关于电视的三个状态
}
void tv::onof()
{
bool b =(state?true:false);
cout<<"the state of tv is"<<" "<<b<<endl;
//判断传入的第一个参数true为1开机状态,flase为0关闭状态
}
void tv::setvoice()
{
if(voice == maxvoice)
{
cout<<"声音最大"<<endl;
return;
}
this->voice++;
cout<<"音量为"<<this->voice<<endl;
}
void tv::setchannel()
{
if(this->channel == maxchannel)
{
cout<<"频道最大"<<endl;
this->channel = 0;
return;
}
this->channel++;
cout<<"频道为"<<" "<<this->channel<<endl;
}
void remote::onof(tv *p1)
{
cout<<"the state of tv is"<<p1->state<<endl;
}
void remote::setvoice(tv *p1)
{
p1->setvoice();
}
void remote::setchannelnum(tv *p1, int num)
{
p1->channel = num;
//遥控器改变频道
}
void remote::setchannel(tv *p1)
{
p1->setchannel();
//打印出现在的频道
}
int main(int argc, char *argv[])
{
test01();
return 0;
}
5、动态数组:
//动态数组,确定数组中成员变量:数组容量大小,存放在里面数组的长度,指向数组开头的指针
//成员函数,判断数组是否满了,满了扩大,并且在末尾添加数据。删除末尾的元素,判断元素个数是否为0。最后遍历
#include <iostream>
#include<stdlib.h>
using namespace std;
class arr
{
private:
int *p;
//有指针要自定义拷贝构造
int size;
int capacity;
//三个成员变量
public:
arr()
{ //初始化最初的数组大小,分配空间,和容量
p = new int[5];
this->size = 0;
this->capacity = 5;
}
arr(int *p,int size,int capacity)
{
this->p = p;
this->size = size;
this->capacity =capacity;
}
arr(const arr &ob)
{
capacity = ob.capacity;
this->p = new int[capacity];
//当前的指针开辟空间。
this->size = ob.size;
memcpy(this->p,ob.p,size*sizeof(int));
//把旧对象的数组的内容,cpy到新对象中。
}
~arr()
{
if(p != nullptr)
{
delete []p;
}
p =nullptr;
}
void push(int newnum);
void pop();
void print();
};
void test01()
{
arr arr1;
arr1.push(10);
arr1.push(20);
arr1.push(30);
arr1.print();
cout<<endl;
//在数组中先插入三个元素打印
arr1.pop();
arr1.pop();
//删除了初始化的最后俩二元素
arr1.push(40);
arr1.push(50);
arr1.push(60);
arr1.push(70);
arr1.push(80);
arr1.push(90);
arr1.print();
}
int main(int argc, char *argv[])
{
test01();
return 0;
}
void arr::push(int newnum)
{ //先判断容量是不是为满了
if(capacity == size)
{
int *temp =new int[2*capacity];
//满了就定义一个零时指针开辟俩倍空间。
memcpy(temp,p,size*sizeof(int));
//把之前的内容拷贝到零时指针。
delete[]p;
p = temp;
capacity = 2*capacity;
}
p[size] =newnum;
//尾插法
size++;
}
void arr::pop()
{ //调用一次删除一个最后的数组元素
if(size == 0)
{
cout<<"数组是空的"<<endl;
return;
}
size--;
}
void arr::print()
{
for(int i =0;i<size;i++){
cout<<p[i]<< " ";
}
}