C++类与对象深入之静态成员与友元及内部类详解
一:静态成员
静态成员就是在成员变量和成员函数前加上关键字static,称为静态成员。C++里面尽量用静态成员变量代替全局变量。
1.1:静态成员分类
1️静态成员变量:
- 所有对象共享同一份数据
- 在编译阶段分配内存
- 类内声明,类外初始化
静态成员函数
- 所有对象共享同一个函数
- 静态成员函数只能访问静态成员变量
1.2:静态成员变量
class Person
{
public:
static int m_A; //静态成员变量
private:
static int m_B; //静态成员变量也是有访问权限的
};
int Person::m_A = 10;
int Person::m_B = 10;
void test01()
{
//静态成员变量两种访问方式
//1、通过对象
Person p1;
p1.m_A = 100;
cout << "p1.m_A = " << p1.m_A << endl;
Person p2;
p2.m_A = 200;
cout << "p1.m_A = " << p1.m_A << endl; //共享同一份数据
cout << "p2.m_A = " << p2.m_A << endl;
//2、通过类名
cout << "m_A = " << Person::m_A << endl;
//cout << "m_B = " << Person::m_B << endl; //私有权限访问不到
}
int main() {
test01();
system("pause");
return 0;
}
代码解释:上述代码我们主要验证了利用两种方式来访问静态成员变量,以及静态成员变量属于整个类,属于类的所有对象
1.3:静态成员函数
class Person
{
public:
static void func()
{
cout << "func调用" << endl;
m_A = 100;
//m_B = 100; //错误,不可以访问非静态成员变量
}
static int m_A; //静态成员变量
int m_B; //
private:
//静态成员函数也是有访问权限的
static void func2()
{
cout << "func2调用" << endl;
}
};
int Person::m_A = 10;
void test01()
{
//静态成员变量两种访问方式
//1、通过对象
Person p1;
p1.func();
//2、通过类名
Person::func();
//Person::func2(); //私有权限访问不到
}
int main() {
test01();
system("pause");
return 0;
}
代码解释:上述代码我们主要验证了利用两种方式来访问静态成员函数,利用对象访问和利用类名访问,以及静态成员函数只可以访问静态成员变量
⚠️⚠️⚠️:为什么不可以访问非静态成员?
⭐️因为没有this指针
1.4:总结特性
- 静态成员为所有类对象所共享,不属于某个具体的类实例
- 静态成员变量必须在类外定义,定义时不加static关键字
- 类静态成员类名::静态成员或者对象.静态成员来访问
- 静态成员函数没有隐含的this指针,不可以访问任何非静态成员
- 静态成员和类的普通成员也一样,也有三种访问权限,也可以有返回值。
1.5:试题示例
❓实现一个类,计算程序中创建了多少个类对象
class A
{
public:
A(){
++_count1;
}
A(const A& aa){
++_count2;
}
// 成员函数也可以是静态,static成员函数没有this指针
static int GetCount1(){
return _count1;
}
static int GetCount2(){
return _count2;
}
//private:
// 静态成员变量属于整个类,所以类的所有对象
static int _count1;
static int _count2; // 声明
};
// 定义
int A::_count1 = 0;
int A::_count2 = 0;
A Func(A a)
{
A copy(a);
return copy;
}
int main()
{
A a1;
A a2 = Func(a1);
cout << a1._count1 << endl;
cout << a2._count1 << endl;
cout << a1._count2 << endl;
cout << a2._count2 << endl;
cout << A::_count1 << endl;
cout << A::_count2 << endl;
cout << a1.GetCount1() << endl;
cout << a2.GetCount2() << endl;
cout << A::GetCount1() << endl;
cout << A::GetCount2() << endl;
system("pause");
return 0;
}
1
1
3
3
1
3
1
3
1
3
请按任意键继续. . .
1.6:C++11成员初始化新玩法
class B
{
public:
B(int b = 0)
:_b(b)
{}
int _b;
};
class A
{
public:
//A()//其实是编译器自己生产的默认构造函数用缺省值初始化
// :a(10)
// , b(20)
// , p((int*)malloc(4))
//{}
void Print()
{
cout << a << endl;
cout << b._b << endl;
cout << p << endl;
cout << n << endl;
}
private:
// 非静态成员变量,可以在成员声明时给缺省值。
int a = 10;
B b = 20;//单参数的构造函数,支持隐式类型的转换
int* p = (int*)malloc(4);
static int n;
//非静态成员变量定义在构造函数
//静态在类外
};
int A::n = 0;
int main()
{
A a;
a.Print();
system("pause");
return 0;
}
二:友元
在程序里,有些私有属性 也想让类外特殊的一些函数或者类进行访问,就需要用到友元的技术
友元的目的就是让一个函数或者类 访问另一个类中私有成员
友元的关键字为friend
友元分为:
- 友元函数
- 友元类
友元的三种实现:
全局函数做友元
类做友元
成员函数做友元
2.1:全局函数做友元
⭐️说明:友元函数可以直接访问类的私有成员,它是定义在类外部的普通成员函数,不属于任何类,但需要在类的内部声明,声明的时候需要加friend关键字。
class Building
{
//告诉编译器 GoodGay全局函数 是 Building类的好朋友,可以访问类中的私有内容
friend void goodGay(Building * building);
public:
Building(){
this->m_SittingRoom = "客厅";
this->m_BedRoom = "卧室";
}
public:
string m_SittingRoom; //客厅
private:
string m_BedRoom; //卧室
};
void goodGay(Building * building){
cout << "好基友正在访问: " << building->m_SittingRoom << endl;
cout << "好基友正在访问: " << building->m_BedRoom << endl;
}
void test01(){
Building b;
goodGay(&b);
}
int main(){
test01();
system("pause");
return 0;
}
代码解释:如上述代码中,我们需要告诉编译器 goodGay全局函数 是 Building类的好朋友,可以访问类中的私有内容
2.2:类做友元
友元类的所有成员函数都可以是另一个类的友元函数,都可以访问另一个类的非公有成员。
- 友元关系是单向的,不具有交换性。
- 友元关系不可以传递。如果B是A的友元,C是B的友元,但是不可以说C是A的友元。
代码示例:
class Building;
class goodGay
{
public:
goodGay();
void visit();
private:
Building *building;
};
class Building
{
//告诉编译器 goodGay类是Building类的好朋友,可以访问到Building类中私有内容
friend class goodGay;
public:
Building();
public:
string m_SittingRoom; //客厅
private:
string m_BedRoom;//卧室
};
Building::Building(){
this->m_SittingRoom = "客厅";
this->m_BedRoom = "卧室";
}
goodGay::goodGay(){
building = new Building;
}
void goodGay::visit(){
cout << "好基友正在访问" << building->m_SittingRoom << endl;
cout << "好基友正在访问" << building->m_BedRoom << endl;
}
void test01(){
goodGay gg;
gg.visit();
}
int main(){
test01();
system("pause");
return 0;
}
代码解释:如上述代码中,我们需要告诉编译器 告诉编译器 goodGay类是Building类的好朋友,可以访问到Building类中私有内容
2.3:成员函数做友元
一个类的成员函数做另一个类的友元。
代码示例:
class Building;//提前声明
class goodGay
{
public:
goodGay();
void visit(); //只让visit函数作为Building的好朋友,可以发访问Building中私有内容
void visit2();
private:
Building *building;
};
class Building
{
//告诉编译器 goodGay类中的visit成员函数 是Building好朋友,可以访问私有内容
friend void goodGay::visit();
public:
Building();
public:
string m_SittingRoom; //客厅
private:
string m_BedRoom;//卧室
};
Building::Building(){
this->m_SittingRoom = "客厅";
this->m_BedRoom = "卧室";
}
goodGay::goodGay(){
building = new Building;
}
void goodGay::visit(){
cout << "好基友正在访问" << building->m_SittingRoom << endl;
cout << "好基友正在访问" << building->m_BedRoom << endl;
}
void goodGay::visit2(){
cout << "好基友正在访问" << building->m_SittingRoom << endl;
//cout << "好基友正在访问" << building->m_BedRoom << endl;
}
void test01(){
goodGay gg;
gg.visit();
}
int main(){
test01();
system("pause");
return 0;
}
代码解释:如上述代码中,我们需要告诉编译器 goodGay类中的visit成员函数 是Building好朋友,可以访问私有内容
三:内部类
3.1:概念
概念:如果一个类定义在另一个类的内部,这个类就叫内部类。注意此时的内部类是一个独立的类,它不属于外部类。更不可以通过外部类的对象去调用内部类。外部类对内部类没有任何的访问权限。
⚠️下面我们看一段代码:
// 内部类
class A
{
private:
static int k;
int h;
public:
// 内部类
class B // B天生就是A的友元
{
public:
void foo(const A& a)
{
cout << k << endl;//OK
cout << a.h << endl;//OK
}
private:
int _b;
};
// A不是B的友元
};
int A::k = 1;
int main()
{
A aa;
cout << sizeof(A) << endl;
A::B bb;
return 0;
}
代码解释:如上述代码中,对于此处的内部类,B天生就是A的友元,所以在B类中可以访问A类的私有成员,但是A不是B的友元。如果内部类是公有属性的话,我们还可以实例化内部类对象。
3.2:特性
⭐️⭐️⭐️特性:
- 内部类可以定义在外部类的public、protected、private都是可以的。
- 注意内部类可以直接访问外部类中的static、枚举成员,不需要外部类的对象/类名。
- sizeof(外部类) = 外部类,和内部类没有任何关系。
到此这篇关于C++类与对象深入之静态成员与友元及内部类详解的文章就介绍到这了,更多相关C++类与对象内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!
相关文章