C++类和对象(下)

1. static成员

1.1 概念

声明为static的类成员称为类的静态成员,用static修饰的成员变量,称之为静态成员变量;用static修饰成员函数,称之为静态成员函数静态成员变量一定要在类外进行初始化。

class Stack
{
public:
	Stack(int capacity = 4)
	{
		cout << "stack()" << endl;
		_a = (int*)malloc(sizeof(int) * 4);
		if (_a == NULL)
		{
			perror("malloc fail");
			return;
		}
		_capacity = 4;
		_top = 0;
	}

	~Stack()
	{
		cout << "~Stack()" << endl;
		free(_a);
		_a = nullptr;
		_top = 0;
		_capacity = 0;
	}

private:
	int* _a = nullptr;
	 static int _top;
	int _capacity = 0;
};

int Stack::_top=0;//简单来说就是要这样写

1.2 特性

1. 静态成员所有类对象所共享,不属于某个具体的对象,存放在静态区。

2. 静态成员变量必须在类外定义,定义时不添加static关键字,类中只是声明。

3. 类静态成员即可用 类名::静态成员 或者 对象.静态成员 来访问。

4. 静态成员函数没有隐藏的this指针,不能访问任何非静态成员。

5. 静态成员也是类的成员,受publicprotectedprivate 访问限定符的限制。

同时一个静态成员在类里面是具有唯一性的,即在调用时都是调用的同一份。

PS:就算再递归中也同样如此。

2. 友元

2.1 概念

简单来说,就是A这个类是B这个类的友元,那么A这个类就可以访问B的private和protected。

但是我们要注意A是B的友元不代表B是A的友元,友元这个属性是具有单向性的。即B不可以访问A的private和protect。

同时友元还具有唯一性,即无法被继承和传递。

友元分为:友元函数友元类
PS:友元这个属性会破坏类的封装性,因为会突破权限访问,所以很多时候能不用就不要用。
友元要先声明在使用。因为编译器是从上向下编译的,所以B这个类要写在A的前面。

 如果说B在A前面声明了也同样是不行的,因为这种做法相当于告诉编译器B的存在,但是却不知道B的成员。

以下这个代码就是一个错误的样例。

class B; // 前向声明类 B(仅告诉编译器“B 存在”,但不知其成员)

// 定义友元函数(此时 B 的结构未知,无法访问成员)
void friendFunc(B& b) {
    b.data = 10; // ❌ 错误!此时编译器不知道 B 有 data 成员
}

class B {
    friend void friendFunc(B&); // 声明友元函数
private:
    int data; // 私有成员
};

2.2 友元函数

友元函数可以直接访问类的私有成员,它是定义在类外部普通函数,不属于任何类,但需要在类的内部声明,声明时需要加friend关键字。
这边B在A前面声明可以是因为不是B里面的一个函数是A的友元,简答来说就是我们在这里只是需要编译器知道B这个类的存在就好。
class B; 

class A {
public:
    void visitB(B& obj); 
};

class B {
private:
    int privateData = 42; 

public:
    friend void A::visitB(B& obj); 
};

void A::visitB(B& obj) {
    cout << "访问 B 的私有数据:" << obj.privateData << endl;
    obj.privateData = 100; 
    cout << "修改后的值:" << obj.privateData << endl;
}

友元函数不能用const修饰。

友元函数可以在类定义的任何地方声明,不受类访问限定符限制。

一个函数可以是多个类的友元函数。

友元函数的调用与普通函数的调用原理相同。

2.3 友元类

友元类的所有成员函数都可以是另一个类的友元函数,都可以访问另一个类中的非公有成员。

下面是一个友元类的简单代码(A是B的友元类)。

class B; 

class A {
public:
    void accessB(B& b); 
};

class B {
private:
    int privateData = 10; 
    friend class A; 
};

void A::accessB(B& b) {
    cout << "访问 B 的私有数据: " << b.privateData << endl; 
    b.privateData = 20; 
    cout << "修改后 B 的私有数据: " << b.privateData << endl;
}

A 如果是 B 的友元类,那 A 就可以访问 B 的所有。 A 如果里面的一个函数是 B 的友元函数,那这个 A 可以通过这个函数去访问 B 的所有。

3. 内部类

 如果一个类A定义在另一个类B的内部,这个类A就叫做内部类。内部类是一个独立的类,它不属于外部类,更不能通过外部类的对象去访问内部类的成员。外部类对内部类没有任何优越的访问权限。

简单来说就是类里面套了一个类。这在一些比较复杂无法简单通过一个类来描述的时候会使用。

内部类就是外部类的友元类。

以下就是一个比较简单的内部类的实现。

#include <iostream>
#include <string>
using namespace std;

class School {
public:
    // 学生内部类
    class Student {
    public:
        Student(string n, int a) 
            : name(n)
            , age(a) 
            {}
        void show() {
            cout << "学生:" << name << ",年龄:" << age << endl;
        }
    private:
        string name;
        int age;
    };

    // 老师内部类
    class Teacher {
    public:
        Teacher(string n, string c) 
            : name(n)
            , course(c)
            {}
        void teach() { 
            cout << "老师:" << name << ",教授课程:" << course << endl;
        }
    private:
        string name;
        string course;
    };

    void welcome() { // 学校欢迎信息
        cout << "欢迎来到" << schoolName << "!" << endl;
    }

private:
    string schoolName = "XX中学"; // 学校名称
};

int main() {
    School school;
    school.welcome(); // 调用外部类方法

    School::Student stu("小李", 15); // 创建内部类学生对象
    School::Teacher tea("张老师", "数学"); // 创建内部类老师对象

    stu.show(); // 调用学生方法
    tea.teach(); // 调用老师方法

    return 0;
}

我们并不是一定要通过内部类来实

现school的,代码里面的实现方式是很多的,我们也可以通过继承来实现以上想要达到的内容。

评论 29
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

啊吧怪不啊吧

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值