2、数据成员(字段)

发布时间:2025-06-24 17:58:54  作者:北方职教升学中心  阅读量:292


可以被当前类及其派生类访问,但不能被类外部直接访问。这三个特性是 OOP 的核心思想,它们通过抽象、this 指针的基本特性

3.2、


3.4、public)来控制成员的访问权限

C++学习笔记:

C++ 进阶之路__Zwy@的博客-CSDN博客

各位于晏,亦菲们,请点赞关注!

我的个人主页:

_Zwy@-CSDN博客


目录

1、限制,不能再随意通过对象直接访问数据,这是C++封装的⼀种体现,这个是最重要的变化。4\

Address of obj: 00A5FBAFAddress of this: 00A5FBAF

this 指针存储的具体过程:
调用栈分配:   

当调用非静态成员函数时,调用对象的地址被压入栈,作为 this 指针传递给函数.

寄存器优化:

在某些平台上,为了优化性能,this 指针会存储在特定的寄存器中(例如 x86 平台的 ECX 寄存器)。类的实例化创建出来的就是对象!

2.1、类域

概念:

在 C++ 中,类域(Class Scope)是指类定义所界定的范围。
VS中默认的对齐数为8
结构体总大小为:最大对齐数(所有变量类型最大者与默认对齐参数取最小)的整数倍。 


 4、

核心点: 

信息隐藏:类的内部细节对外部不可见。对象大小

在C++中,对象的大小是一个与内存管理息息相关的重要概念。
这种情况下,对象的大小会增加一个指针的大小(通常是 4 字节或 8 字节,取决于平台)。

class MyClass {private:    int value;public:    MyClass& setValue(int v) {   // 返回当前对象的引用        this->value = v;        return *this;            // *this 解引用指向当前对象    }    void display() {        std::cout << "Value = " << value << std::endl;    }};int main() {    MyClass obj;    obj.setValue(10).setValue(20).display();  // 链式调用    return 0;}

输出:setValue返回*this(当前对象的引用),使调用者可以连续调用其他方法。常用于继承,派生类可以直接访问基类中的受保护成员。模块化和代码复用性,使得程序更易于设计、例如:

class Example {protected:    int protectedVar;    void protectedMethod() {        cout << "protectedMethod" << endl;    }};int main() {    Example obj;   // obj.protectedMethod(); // 错误:类外部无法访问 protected 成员    return 0;}

 编译器报错信息: 

test.cpp: In function ‘int main()’:test.cpp:9:10: error: ‘void Example::protectedMethod()’ is protected     void protectedMethod() {          ^test.cpp:15:25: error: within this context     obj.protectedMethod(); // 错误:类外部无法访问 protected 成员


使用访问限定符的原因和场景:

数据隐藏和封装:通过使用private和protected访问限定符,可以将类的数据成员隐藏起来,只允许通过类提供的公有成员函数来访问和修改数据。


对象大小的计算涉及到内存对齐,我们先来理解什么是内存对齐?

2.3.2、struct&&class 

C语言中,struct被用来定义结构体,C++兼容C语言的用法,同时C++中,struct还可以用来定义类

 实现一个以struct关键字定义的类:

struct Example {    int var;  // 默认是 public};

 实现一个以class关键字定义的类:

class Example {    int var;  // 默认是 private};

class和struct定义类的区别:

class定义的类中成员没有被访问限定符修饰时默认为private,而struct定义的类中成员没有被访问限定符修饰时默认为public


1.4、类

1.1、this指针的使用场景

区分成员变量和局部变量/参数:

当成员变量与函数参数或局部变量同名时,可以使用 this指针来明确指向成员变量。


嵌套结构体的内存对齐:

嵌套结构体的内存对齐规则
嵌套结构体的每个成员仍然遵循自身的对齐规则。


汇编层面理解:

假设使用 x86 架构,编译器生成的汇编代码会将 this指针存储在 ECX寄存器中:

C++:

class MyClass {public:    void func() {        std::cout << "Function called" << std::endl;    }};int main() {    MyClass obj;    obj.func();    return 0;}

汇编:(简化)

; obj.func() 的调用过程mov ecx, OFFSET obj    ; 将 obj 的地址存储到 ECX(this 指针)call MyClass::func     ; 调用 func,this 指针已传入

在调用 func() 之前,编译器会将 obj 的地址存储到寄存器 ECX。静态成员函数不含this指针

静态成员函数属于类本身,而不属于某个具体对象。维护和扩展。访问限定符

在 C++ 中,访问限定符用于控制类的成员(包括数据成员和成员函数)的可访问性。静态成员函数不含this 指针

3.5、

class Animal {public:    string name;    int age;    void eat() {        std::cout << name << " is eating." << std::endl;    }};int main() {    Animal dog;         // 对象:dog    dog.name = "Buddy";    dog.age = 3;    dog.eat();          // 调用方法    return 0;}

 多个对象可以由同一个类创建,每个对象都有自己的属性值。类和对象的关系

2.3、简单来说,this 指针表示调用该函数的具体对象的地址。

Size of Empty: 1 bytes

完整示例:

class Test {    int a;             // 非静态数据成员    static int b;      // 静态数据成员    void func() {}     // 成员函数    virtual void vfunc() {} // 虚函数};int main() {    std::cout << "Size of Test: " << sizeof(Test) << " bytes" << std::endl;    return 0;}

输出:sizeof(Test) 只包括非静态数据成员a的大小和虚函数表指针大小,成员函数 func() 和虚函数代码不影响对象大小,它们是共享的代码段。例如:

class Example {public:    int publicVar;    void publicMethod() {        std::cout << "Public Method" << std::endl;    }};int main() {    Example obj;    obj.publicVar = 10;         // 类外部可以访问    obj.publicMethod();         // 类外部可以访问    return 0;}

1.2.2、

通过成员函数操作栈,具有更好的封装性和安全性。因此,它们不需要 this指针。public

public为公有访问限定符,在类定义中,使用public关键字来声明公有成员。类的定义

1.2、对象的定义—实例化

2.2、 


2.2、protected、this 指针:非静态成员函数里指向当前对象,用于区分变量,静态函数无,本质特殊且有存储传递方式。对象将数据和操作(行为)结合在一起,表示真实世界中的某个具体实体或抽象概念。
虚函数表指针(对于多态类):
如果类包含虚函数,编译器通常会在对象中存储一个指向虚函数表(vtable)的指针,用于实现运行时多态。例如:

class Example {private:    int privateVar;    void privateMethod() {        std::cout << "Private Method" << std::endl;    }};int main() {    Example obj;    // obj.privateVar = 5;  // 错误:无法直接访问 private 成员    return 0;}

 编译器报错信息:

test.cpp: In function ‘int main()’:test.cpp:8:9: error: ‘int Example::privateVar’ is private     int privateVar;         ^test.cpp:15:10: error: within this context      obj.privateVar = 5;  // 错误:无法直接访问 private 成员


1.2.3、

在 C++ 中,类与对象是根基。 

class MyClass {public:    static int staticVar;  // 静态成员声明    static void staticMethod() {        std::cout << "Static Method: " << staticVar << std::endl;    }};// 静态成员的初始化int MyClass::staticVar = 0;int main() {    MyClass::staticVar = 10;      // 通过类名访问    MyClass::staticMethod();      // 调用静态方法    return 0;}

 嵌套类与作用域:

嵌套类的作用域局限于外部类,但可以访问外部类的 private成员(如果外部类提供了访问机制)。对象的定义—实例化

类是模板,对象是实例:类定义了某种类型的结构和行为,而对象是按照类的模板创建出来的实际实例。private)。

访问权限作用域从该访问限定符出现的位置开始直到下⼀个访问限定符出现时为至,如果后面没有访问限定符,作用域就到 }即类结束。访问限定符

1.2.1、

class Rectangle {public:    int width, height;    int area() {        return width * height;    }};int main() {    Rectangle rect1, rect2;    rect1.width = 5; rect1.height = 10;    rect2.width = 3;  rect2.height = 6;    std::cout << "Area of rect1: " << rect1.area() << std::endl;    std::cout << "Area of rect2: " << rect2.area() << std::endl;    return 0;}

 输出:

Area of rect1: 50Area of rect2: 18

2.3、成员函数(方法)。例如实现一个简单的类:

// 定义类class ClassName {private:    // 私有成员和函数    int _privateField;    void privateMethod();protected:    // 受保护成员和函数    int _protectedField;    void protectedMethod();public:    // 公有成员和函数    int _publicField;    void publicMethod();};

 为了区分成员变量,⼀般来说会在成员变量前加上下划线_,但这并不是C++的语法规定,而是程序员使用的惯例!


定义在类中的成员函数,一般默认为inline内联函数,编译器会尝试将这样的函数内联以减少函数调用的开销,但这只是一个建议,编译器可能根据实际情况选择是否执行内联。

1.2.1、对象

2.1、当 func 执行时,this 指针指向 obj。public

1.2.2、
2、

输出:

Size of Example: 7

使用alignas控制对齐 

struct Example {    alignas(8) char a;  // 强制 8 字节对齐    int b;};int main() {    std::cout << "Size of Example: " << sizeof(Example) << std::endl;    return 0;}

输出:

Size of Example: 8

2.3.2、

class Outer {private:    int privateVar;public:    class Inner {    public:        void accessOuter(Outer& o) {            o.privateVar = 10;  // 访问外部类的 private 成员        }    };};int main() {    Outer outer;    Outer::Inner inner;    inner.accessOuter(outer);    return 0;}

命名空间与类域:

类域的定义通常嵌套在命名空间中,用于防止名称冲突。对象是具体的,实例化类后在内存中创建。
4、对象的大小并不仅仅是简单地将类中非静态成员变量的大小相加,还受到内存对齐、

内存对齐的规则:

第⼀个成员在与结构体偏移量为0的地址处。类名通常采用大写字母开头的驼峰命名法,类的主体部分包含在一对花括号{}中,在花括号内部可以定义成员变量和成员函数,类中定义的变量叫做成员变量,类中定义的函数叫做成员函数,并且可以使用访问修饰符(private、
3、

外部结构体的大小必须是所有成员的最大对齐系数的整数倍,包括嵌套结构体的对齐。嵌套类。struct&&class 

1.4、
访问控制:通过访问修饰符(private, protected, public)限制外部对类成员的访问。private

1.2.3、

x = 10

返回当前对象自身(实现链式调用):

this指针可以返回当前对象的引用,实现链式调用。
在函数调用栈上,this 指针作为一个隐藏参数存储于栈内,具体存储位置取决于编译器实现与调用约定


this 指针的传递机制:
在调用非静态成员函数时,编译器会将调用对象的地址传递给该函数,生成的机器代码会将对象地址存储到 this 指针中。
封装性:对象隐藏其内部实现,通过方法(行为)与外界交互。

namespace _Zwy {    class MyClass {    public:        void method() {            std::cout << "Inside MyNamespace::MyClass" << std::endl;        }    };}int main() {    _Zwy::MyClass obj;    obj.method();    return 0;}

2、对象

对象是面向对象编程(OOP)中的一个核心概念,是一个类的实例。这有助于实现数据的封装,防止外部代码随意修改类的内部状态,提高代码的可维护性和安全性。
静态成员变量:
静态成员变量属于类而不属于某个对象,因此也不包含在对象大小中

类的定义以class关键字开始,后面跟着类名。可以在类的任何地方以及类的外部访问。this指针的存储和传递

 4、this指针的本质

 在底层实现中,this指针是通过编译器隐式传递给非静态成员函数的

class MyClass {public:    void func() {        std::cout << "Function called" << std::endl;    }};int main() {    MyClass obj;    obj.func();    return 0;}

如上代码,实际上被编译器转换为:(不能在实参和形参的位置显示的写this指针(编译时编译器会处理),但是可以在函数体内显示使用this指针

void MyClass::func(MyClass* this) {   // 编译器自动传递 this 指针    std::cout << "Function called" << std::endl;}int main() {    MyClass obj;    MyClass::func(&obj);  // 隐式传递 this 指针    return 0;}

编译器会自动将 this 指针传递给成员函数,因此在函数内部可以访问调用对象的成员。

Value = 20

3.3、对象大小

2.3.1、继承和多态。 

 C++中数据和函数都封装到了类里面,通过访问限定符进行了、决定对象大小的因素

2.3.2、C++实现stack

4.2、虚函数表指针占 4 字节(在 32 位系统)或 8 字节(在 64 位系统)

Size of MyClass: 8 bytes

3、

3.1、填充字节以及类中是否包含虚函数等因素的影响

2.3.1、注意:一般的成员变量不期望被外界访问,都会修饰为private或者protected ,一般对外提供服务的成员函数都会修饰为public


1.3、
隐式传递:this 指针是由编译器自动提供的,无需显式传递。C++ 有三种访问限定符:public(公有)、this 指针的基本特性

this 是一个指针:指向当前对象的内存地址。对象大小的计算 

仅包含非静态数据成员:

class MyClass {    int a;      // 4 bytes    char b;     // 1 byte (but padded to 4 bytes for alignment)    double c;   // 8 bytes};int main() {    std::cout << "Size of MyClass: " << sizeof(MyClass) << " bytes" << std::endl;    return 0;}

输出:

Size of MyClass: 16 bytes

包含静态成员:

class MyClass {    int a;              // 4 bytes    static int b;       // 静态成员,不计入对象大小};int main() {    std::cout << "Size of MyClass: " << sizeof(MyClass) << " bytes" << std::endl;    return 0;}

输出: 4字节(只包括 int a的大小)

Size of MyClass: 4 bytes

空类:

class Empty {};int main() {    std::cout << "Size of Empty: " << sizeof(Empty) << " bytes" << std::endl;    return 0;}

输出C++ 要求每个对象在内存中有唯一地址,因此即使空类的大小为 1 字节。类和对象的关系

类是抽象的,定义了一种类型的结构和行为。内存对齐

2.3.2、类的定义

在 C++ 中,类 是面向对象编程的核心概念之一。
2、数据成员(字段)。类:自定义类型,访问限定符控权限,struct 与 class 有别,有类域概念。C语言实现stack

C++知识总结 


1、
数据和操作是分开的,封装性较差。

class Example {public:    void inlineMethod() {       // 默认是 inline        std::cout << "Inline Method" << std::endl;    }};

等价于:

inline void Example::inlineMethod() {    std::cout << "Inline Method" << std::endl;}

1.2、private

private为私有访问限定符,在类定义中,使用private关键字来声明私有成员,只能在类内部访问,类的外部或派生类无法直接访问,通常用于保护类的内部实现细节。 

简单的嵌套结构体:

struct Inner {    char a;   // 1 字节    int b;    // 4 字节};struct Outer {    char x;       // 1 字节    Inner inner;  // 嵌套结构体    short y;      // 2 字节};int main() {    std::cout << "Size of Inner: " << sizeof(Inner) << " bytes" << std::endl;    std::cout << "Size of Outer: " << sizeof(Outer) << " bytes" << std::endl;    return 0;}

输出:

Size of Inner: 8 bytesSize of Outer: 16 bytes

内存布局分析:

成员字节偏移量占用字节说明
char x01成员 x占 1 字节
填充13填充 3 字节,使下一个成员按 4 字节对齐
Inner(嵌套结构体)48Inner的大小为 8 字节(按 4 字节对齐)
short y122成员 y占 2 字节
填充142末尾填充,使结构体总大小按 4 字节对齐

总大小:1 + 3 + 8 + 2 + 2 = 16 字节


优化后的结构体(成员顺序调整) 

struct OuterOptimized {    char x;       // 1 字节    short y;      // 2 字节    Inner inner;  // 嵌套结构体};

内存布局分析: 

成员字节偏移量占用字节说明
char x01成员 x占 1 字节
short y22成员 y占 2 字节
填充44填充 4 字节,使下一个成员按 8 字节对齐
Inner(嵌套结构体)88Inner的大小为 8 字节(按 4 字节对齐)

总大小:1 + 2 + 1 + 8 = 12 字节,按最大对齐 4 字节,最终为 16 字节。对象大小的计算 

3、决定对象大小的因素

对象的大小只包括类中非静态数据成员(成员变量)所占的内存空间:

静态数据成员、this指针 

在 C++ 中,this 是一个特殊的指针,指向当前对象本身。
行为(成员函数):对象的操作能力(由类中的方法定义)。它是非静态成员函数的一个隐式参数,只有在调用类的非静态成员函数时,this 指针才会被传递给函数

编译器生成代码:

编译器会在函数调用时,将对象地址传递给函数中的 this 指针,确保其在函数内部可用

构造函数和析构函数自动管理内存(new/delete)


C++知识总结 

1、
常量性:this 指针本身是不可修改的,它只能指向当前对象。


3.2、
类域内的成员通常通过访问限定符控制访问权限(public、

class MyClass {    int privateVar;  // 私有成员:只能在类内部访问public:    int publicVar;   // 公有成员:可以从类外部访问    void method() {        privateVar = 10;  // 类内部可以访问 private 成员        publicVar = 20;   // 类内部可以访问 public 成员    }};int main() {    MyClass obj;    obj.publicVar = 5;    // 可以访问 public 成员    // obj.privateVar = 5; // 错误:无法访问 private 成员    return 0;}

访问控制与作用域规则:

在类中,作用域和访问控制由访问限定符决定:

访问限定符类内部访问派生类访问类外部访问
private可以不可以不可以
protected可以可以不可以
public可以可以可以

静态成员与类域:

静态成员属于类本身,而不是类的实例,必须在类外初始化。类域

2、
内存对齐:
编译器会为数据成员添加填充字节,以确保数据对齐符合系统要求。protected

1.3、C语言和C++实现stack对比

面向对象编程(Object-Oriented Programming, OOP)的三大特点是封装、C 与 C++ 实现 stack:C++ 靠类封装,清晰安全;C 语言用结构体与函数指针,灵活但手动管理内存且耦合度高。最后,类的定义以一个分号;结束。它允许派生类访问基类的部分成员,同时又限制了外部对这些成员的访问,有助于实现面向对象编程中的继承和多态特性。
只能用于非静态成员函数:静态成员函数不属于任何具体对象,因此没有 this 指针。

Size of Test: 8 bytes

 内存对齐的影响:

class MyClass1 {    char a;   // 1 byte    int b;    // 4 bytes    char c;   // 1 byte};class MyClass2 {    char a;   // 1 byte    char c;   // 1 byte    int b;    // 4 bytes};int main() {    std::cout << "Size of MyClass1: " << sizeof(MyClass1) << " bytes" << std::endl;    std::cout << "Size of MyClass2: " << sizeof(MyClass2) << " bytes" << std::endl;    return 0;}

输出: 

Size of MyClass1: 12 bytesSize of MyClass2: 8 bytes

虚函数的影响:(继承和多态会讲到)

如果类中包含虚函数,每个对象会多出一个指针(通常是 4 或 8 字节,取决于系统架构),指向虚函数表(V-Table)。封装的本质在于保护对象的内部状态,同时为外部提供受控的访问接口。

class MyClass {private:    int x;public:    void setX(int x) {     // 参数和成员变量同名        this->x = x;       // 使用 this 指针区分成员变量和参数    }    void display() {        std::cout << "x = " << this->x << std::endl;    }};int main() {    MyClass obj;    obj.setX(10);      // 设置成员变量 x    obj.display();     // 输出:x = 10    return 0;}

输出: 在 setX函数中,this->x明确表示成员变量 x,而参数 x覆盖了同名的成员变量。


C++:

提供类(class) 和 对象 的概念,将数据和行为封装在一起。
对外提供接口:通过方法访问或修改内部数据,保证对象状态的完整性和安全性。this指针的使用场景

3.3、
对象的组成:属性(数据成员):对象的状态(由类中的字段定义)。
一般来说,this 指针存储在寄存器中(如 ECX 寄存器,在 x86 的 cdecl 调用约定 下),也可能存储在栈内存中,具体取决于平台和编译器


this指针的隐式传递:

class MyClass {public:    void display() {        std::cout << "Address of this: " << this << std::endl;    }};int main() {    MyClass obj;    std::cout << "Address of obj: " << &obj << std::endl;    obj.display();    return 0;}

输出:在调用 obj.display() 时,this 指针被隐式传递给 display() 函数。对象:类实例化产物,大小受成员变量及内存对齐影响,体现类的具体化。
注意:对齐数 = 编译器默认的⼀个对齐数与该成员大小的较小值。内存对齐

为什么需要内存对齐?
CPU 从内存读取数据时,并不是逐字节读取,而是按一定的 字节块(如 4 字节或 8 字节) 读取。 

class Car {public:    string brand;  // 属性:品牌    int speed;     // 属性:速度    void drive() {  // 行为:驾驶        std::cout << brand << " is driving at " << speed << " km/h." << std::endl;    }};int main() {    Car car;              // 创建对象 car1    car.brand = "Toyota"; // 设置属性    car.speed = 100;      // 设置属性    car.drive();          // 调用行为    return 0;}

特点:

唯一性:每个对象在内存中是独立存在的,具有唯一的地址。

示例:

struct Example {    char a;     // 1 字节    int b;      // 4 字节    short c;    // 2 字节};int main() {    std::cout << "Size of Example: " << sizeof(Example) << std::endl;    return 0;}

输出:

Size of Example: 12

 内存布局:

成员字节占用备注
char a11 字节
填充3填充到 4 字节对齐
int b44 字节对齐
short c22 字节
填充2填充到 4 字节整数倍

总大小:1 + 3 + 4 + 2 + 2 = 12 字节


调整成员顺序减少填充:

struct Optimized {    char a;     // 1 字节    short c;    // 2 字节    int b;      // 4 字节};int main() {    std::cout << "Size of Optimized: " << sizeof(Optimized) << std::endl;    return 0;}

 输出:

Size of Optimized: 8

优化后的内存布局:

成员字节占用备注
char a11 字节
short c2紧接着占 2 字节
填充1填充到 4 字节对齐
int b44 字节对齐

总大小:1 + 2 + 1 + 4 = 8 字节

通过调整成员的顺序,结构体的大小从 12 字节 减少到了 8 字节。this指针 

3.1、C++实现stack

#include<iostream>#include<assert.h>using namespace std;typedef int STDataType;class Stack{public:	// 成员函数	void Init(int n = 4)	{		_a = (STDataType*)malloc(sizeof(STDataType) * n);		if (nullptr == _a)		{			perror("malloc failed");			return;		}		_capacity = n;		_top = 0;	}    void Push(STDataType x)	{		if (_top == _capacity)		{			int newcapacity = _capacity * 2;			STDataType* tmp = (STDataType*)realloc(_a, newcapacity *				sizeof(STDataType));			if (tmp == NULL)			{				perror("realloc failed");				return;			}			_a = tmp;			_capacity = newcapacity;		}		_a[_top++] = x;	}	void Pop()	{		assert(_top > 0);		--_top;	}	bool Empty()	{		return _top == 0;	}	int Top()	{		assert(_top > 0);		return _a[_top - 1];	}	void Destroy()	{		free(_a);		_a = nullptr;		_top = _capacity = 0;	}private:// 成员变量	STDataType* _a;	size_t _capacity;	size_t _top;};

4.2、当然封装不仅仅是这样的,我们后面还需要不断的去习。 

4.1、它们奠定了 C++ 世界的基石,是开启编程进阶之路的必经之门,本文主要讲解最基本的类和对象的定义,在进阶部分会对类和对象进行更深层次的剖析,为后续C++飞升之路打造最有力的制胜法宝!

如上的讲解只是我的一些拙见,如有不足之处,还望各位大佬不吝在评论区予以斧正,感激不尽!创作不易,还请多多互三支持!你们的支持是我最大的动力!


需要显式传递结构体指针,操作数据。


多层嵌套结构体:

struct Level1 {    char a;    // 1 字节    int b;     // 4 字节};struct Level2 {    Level1 l1; // 8 字节    double d;  // 8 字节};struct Level3 {    char x;       // 1 字节    Level2 l2;    // 16 字节};

内存布局分析: 

成员字节偏移量占用字节说明
char x01成员 x占 1 字节
填充17填充 7 字节,使下一个成员按 8 字节对齐
Level2 l2816嵌套结构体 Level2的大小为 16 字节

总大小:1 + 7 + 16 = 24 字节 


自定义对齐规则

C++ 提供了#pragma pack指令和alignas关键字,允许我们自定义内存对齐方式。作为类的实例,对象不仅封装了数据,还反映了程序运行时的内存占用情况。

输出int a 占 4 字节。类的成员(包括成员变量和成员函数)都在这个类域内。在对象的内存中,this 指针并不占据实际空间,它只是一个调用函数时的临时指针。this指针的存储和传递

this 指针的存储位置:
this 指针并不是一个变量,而是由编译器在函数调用时隐式传递给非静态成员函数的一个指针。
3、它是一种用户定义的数据类型,用于描述一组具有相同特性(属性)和行为(方法)的对象。成员函数以及虚函数的代码(包括它们的地址)都不包含在对象本身的大小中
成员函数:
成员函数在编译阶段会被编译成代码段中的独立函数,所有实例共享一份函数代码。
外部结构体会将嵌套结构体视为一个整体,嵌套结构体的大小和对齐要求会影响外部结构体的内存布局。C语言实现stack

#include<stdio.h>#include<stdlib.h>#include<stdbool.h>#include<assert.h>typedef int STDataType;typedef struct Stack{	STDataType* a;	int top;	int capacity;}ST;void STInit(ST* ps){	assert(ps);	ps->a = NULL;	ps->top = 0;	ps->capacity = 0;}void STDestroy(ST* ps){	assert(ps);	free(ps->a);	ps->a = NULL;	ps->top = ps->capacity = 0;}void STPush(ST* ps, STDataType x){	assert(ps);// 满了, 扩容	if (ps->top == ps->capacity)	{		int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;		STDataType* tmp = (STDataType*)realloc(ps->a, newcapacity *			sizeof(STDataType));		if (tmp == NULL)		{			perror("realloc fail");			return;		}		ps->a = tmp;		ps->capacity = newcapacity;	}	ps->a[ps->top] = x;	ps->top++;}bool STEmpty(ST* ps){	assert(ps);	return ps->top == 0;}void STPop(ST* ps){	assert(ps);	assert(!STEmpty(ps));	ps->top--;}STDataType STTop(ST* ps){	assert(ps);	assert(!STEmpty(ps));	return ps->a[ps->top - 1];}int STSize(ST* ps){	assert(ps);	return ps->top;}

C 语言:

没有类和对象的概念,只能通过结构体struct和函数的组合来实现栈。

类域的范围:

类域指类内部定义的成员的作用范围,包括:

1、因此,成员函数并不占用每个对象的存储空间。通过下面的对比,我们可以先感受一下封装的魅力!

封装的本质:

封装是面向对象编程(OOP)的核心特性之一,强调将数据和操作封装在一起,通过控制访问权限实现信息隐藏和接口抽象。

class MyClass {public:    static void staticFunc() {        // std::cout << this;  // 错误:静态函数没有 this 指针        std::cout << "Static function called." << std::endl;    }};int main() {    MyClass::staticFunc();    return 0;}

输出:

Static function called.

静态函数无法访问非静态数据成员,因为它们不依赖于具体对象,没有this指针


3.5、类

1.1、private(私有)和protected(保护),这些限定符在类的定义中使用,用于指定类的成员在类外部的可访问程度。
继承和多态:protected访问限定符在类的继承关系中起到重要作用。如果数据不对齐,CPU 需要执行额外的操作来读取数据,影响性能。this指针的本质

3.4、C语言和C++实现stack对比

4.1、在函数内部,this 指向当前对象 obj 的地址。protected

protected为保护访问限定符,在类定义中,使用protected关键字来声明保护成员,介于 private 和 public 之间。protected、
其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。这里的封装的本质是⼀种更严格规范的管理,避免出现乱访问修改的问题。

使用#pragma pack控制对齐

#pragma pack(1)  // 设置对齐字节为 1struct Example {    char a;    int b;    short c;};#pragma pack()  // 恢复默认对齐int main() {    std::cout << "Size of Example: " << sizeof(Example) << std::endl;    return 0;}

 #pragma pack(1)表示按 1 字节对齐,不会添加填充字节,但可能降低性能。