day6 类成员指针 友元
类成员指针
在C++中可以定义指针,指向类成员或成员函数,然后通过指针访问类的数据成员和成员函数。在这里实际上是指针记录了成员在类的偏移量。
指向普通变量和函数的指针
#include<iostream>
using namespace std;
void fun(int a){
cout<<a<<endl;
}
int main(){
int i=10;
int *p=&i;//变量指针
cout<<*p;
void (*pf)(int)=fun;//函数指针
pf(10);//
return 0;
}
指向类数据成员的指针
1、非静态成员
数据成员:
数据类型 +类名::+ *指针名
初始化
数据类型 +类名::+ *指针名=&类名::+非静态数据成员
函数成员:
定义方式与非类相似绑定类名
数据类型 +(类名:: *指针名)(参数列表)=&类名::函数名
2、解引用
一开始就说到,类成员指针只是记录了成员在类中的偏移量,所以使用指针时必须要指定一个类的对象。
如:
#include<iostream>
using namespace std;
class A{
public:
A(int input):data(input){}
void dis(){
cout<<data;
}
int data;
}
int main(){
A a1(10);//栈对象
A *a2=new A(20);//堆对象
int A::*p=&A::data;//声明p为data的指针
cout<<a1.*p<<endl//使用解引用
cout<<a2->*p<<endl;//使用解引用
void (A::*pf)()=&A::dis;//声明函数指针
(a1.*pf)();
(a2->*pf)();//解引用
return 0;
}
3、静态成员
静态数据成员定义不需要和类绑定,不需要绑定类对象。
使用方法:
#include<iostream>
using namespace std;
class A{
public:
static int data;
static void dis(){
cout<<data;
};
}
int main(){
int *p=&A::data;
void (*pf)()=&A::dis;
cout<<*p<<endl;//直接使用
pf();
return 0;
}
友元
定义:友元函数是可以直接访问类的私有成员的非成员函数他可以是定义在类外面的普通函数,不属于任何类,然后需要在类内声明,加上关键字friend
格式:
普通函数:
friend 类型 函数名(参数);
类成员函数:
friend 类型 类名:: 函数名(参数)
友元类:
friend class B;
1、同类间可以随意访问其数据,无权限限制。异类间可以通过友元来访问异类成员。
如把A声明为B的友元类,则A可以通过B的对象访问B的私有成员。
2、在类内把一个函数,或异类成员函数,类,声明为友元(加上关键字friend)。则称为该类的友元函数,友元类。
如这样是没办法访问A类的成员数据的。
但声明为友元则可以
class A{
friend class B;
private:
int data=5;
};
class B{
public:
void dis(A&a){
cout<< a.data;
}
};
int main(){
B b;A a;
b.dis(a);
}
3、友元还可以是类成员函数
4、注意事项
(1) 友元关系不能被继承。(但可以通过父子类间的赋值兼容性原理或类型转换来调用父子类的友元)继承与派生中关于赋值兼容的描述
(2) 友元关系是单向的,不具有交换性。若类B是类 A的友元,类 A不一定是类B的 友元,要看在类中是否有相应的声明。
(3) 友元关系不具有传递性。若类 B是类A的友元,类C是B的友元,类C不一定是 类A的友元,同样要看类中是否有相应的申明
写在最后
1、函数调用“()”操作符需要左侧是一个指针,函数名可以隐式转换成函数指针。
2、友元不是类成员,但是它可以访问类中的私有成员,因为友元不是授权方的成员,所以它不受public
private
和protected
的影响。所以可以把所有的友元写一块,方便阅读。