再探“构造函数”(2)友元and内部类
文章目录
- 一. 友元
- ‘全局函数’作友元
- ‘成员函数’作友元
- ‘类‘作友元
- 内部类
一. 友元
何时会用到友元呢?
当想让(类外面的某个函数/其它的类)访问 某个类里面的(私有或保护的)内容时,可以选择使用友元。
友元提供了一种突破(类访问限定符 封装)的方式,即在类外面也可以访问类里面的私有/保护成员。
友元的关键字:
friend
友元的声明通常位于类的声明中,但其实现则位于类外部。
- 友元分为2种:友元函数和友元类
友元函数是一种特殊的函数,且它的声明是在类的内部,但它并不是类的成员函数
还有一个注意点是,只有类的静态成员或者静态成员函数才能直接用类名去访问。
class A
{
public:
A(int a1)
:_a1(3)
{
}
int _a1=1;
};
int main()
{
//这个是错误的
std::cout << A::_a1 << std::endl;
//这个是正确的
A aa1(9);
std::cout << aa1._a1 << std::endl;
}
class A
{
public:
A(int a2)
{
}
static int _a1;
int _a2 = 9;
};
static int _a1 = 8;//static成员在全局初始化
int main()
{
//静态成员函数可以用类名去访问
std::cout << A::_a1 << std::endl;
}
‘全局函数’作友元
(某个全局函数) 想要访问 (类A里的私有成员),直接访问的话,编译器会报错。
办法:我们可以告诉编译器,这个全局函数是类A的好朋友,它是可以访问类A的私有成员的,可以放心,不会出事儿。
措施:在类的内部声明,全局函数是友元
//类A
class A
{
friend void quanjv(A& a);
public:
A(int a1, int a2)
:_a1(a1)
, _a2(a2)
{
}
private:
int _a1;
int _a2;
};
//全局函数
void quanjv(A& a)
{
std::cout << a._a1 << std::endl;
}
int main()
{
A a1(1, 2);
quanjv(a1);
return 0;
}
‘成员函数’作友元
(B的成员函数)想要访问(A的私有成员)
在A中声明友元函数,告诉编译器,B的某个成员函数是A的友元函数,可以访问A的私有成员。
class A
{
friend void B::fang();
public:
A(int a1)
:_a1(3)
{
}
private:
int _a1=1;
};
class B
{
public:
B(int b1)
:_b1(3)
{
}
void fang()
{
A a1(9);
std::cout << a1._a1 << std::endl;
}
private:
int _b1 = 1;
};
int main()
{
B b1(8);
b1.fang();
return 0;
}
‘类‘作友元
在A类中声明友元函数,告诉编译器,B类是A类的好朋友,可以访问A类的私有成员
class A
{
//告诉编译器,类B是类A的好朋友,B可以使用A的私有,保护成员
friend class B;
public:
A(int a1)
:_a1(3)
{
}
private:
int _a1 = 1;
};
class B
{
public:
B(int b1)
:_b1(3)
{
}
void fang()
{
A a1(9);
std::cout << a1._a1 << std::endl;
}
private:
int _b1 = 1;
};
int main()
{
B b1(8);
b1.fang();
return 0;
}
内部类
我们可以将其理解为嵌套,即:一个类里面,嵌套了另一个类。(在里面的那个类,叫做内部类。)
class A
{
public:
class B
{}
}
那什么时候考虑使用内部类呢?
如果说,类A的出现就是为了供类B使用,那么可以将类A设置为B的内部类。如果将A 放在private/protected位置,那么A类就是B类的专属内部类,其他地方都用不了。
- 内部类的本质是:封装。
- 内部类是一个独立的类。跟定义在全局的类相比,唯一不同的就是:内部类受外部类的类域限制and访问限定符限制。
- 内部类是外部类的友元。
- 当计算外部类的大小sizeof时,内部类不计算在其中。