C++ 类、结构体与共用体详解:语法特性与内存布局
C++ 语言中类(class)、结构体(struct)和共用体(union)是构建数据和行为的核心容器。类用于实现面向对象编程,支持封装、继承和多态;结构体侧重于数据聚合,但在 C++ 中具备成员函数能力;共用体则通过共享同一块内存来实现类型转换或节省空间。理解它们的默认权限、生命周期管理及内存布局,是编写高效 C++ 程序的基础。
一、类 class:面向对象的基础
类是 C++ 面向对象特性的核心,是对具有相同属性和行为的对象的抽象。与 C 语言不同,C++ 的类支持访问控制、继承和多态机制。虽然 C++ 没有独立的“接口”关键字,但可以通过纯虚函数模拟接口功能,且支持多继承。
第 1 步:定义类的结构与成员访问权限
类由头文件和实现文件组成,需明确定义私有、公共和保护成员。访问修饰符决定了外部对类内部数据的可见性:
private:私有成员,仅类自身及友元可访问,外部不可见。public:公共成员,任何地方均可访问。protected:保护成员,类自身及子类可访问,外部不可见。
第 2 步:实现构造函数与析构函数
构造函数用于对象创建时的初始化,析构函数用于对象销毁前的资源清理。两者的名称必须与类名一致(析构函数加波浪号),且无返回类型。
class Fruit {
private:
int count;
public:
// 声明构造函数
Fruit();
// 声明析构函数
~Fruit();
// 内联定义的成员函数
int getCount() { return count; }
};
// 在类外部实现构造函数
Fruit::Fruit() {
std::cout << "Create fruit" << std::endl;
}
// 在类外部实现析构函数
Fruit::~Fruit() {
std::cout << "Fruit deleted" << std::endl;
}
第 3 步:使用友元函数突破访问限制
友元函数(Friend Function)不属于类的成员,但被授权访问类内部的 private 和 protected 成员。通常在类定义中使用 friend 关键字声明。
#include <iostream>
using namespace std;
class Fruit {
private:
int count = 0;
public:
Fruit();
~Fruit();
// 声明友元函数
friend void printCount(Fruit &ft);
};
// 友元函数定义在类外部
void printCount(Fruit &ft) {
// 直接访问私有成员
cout << ft.count << endl;
}
int main() {
Fruit f;
printCount(f); // 输出 0
return 0;
}
第 4 步:实现继承、虚函数与多态
C++ 支持公有继承(public)及多继承。为了实现运行时多态,需要使用虚函数(Virtual Function)。若父类存在未实现的虚函数(纯虚函数),该类变为抽象类,不能实例化,必须通过子类调用。
- 普通函数调用:根据指针/引用类型决定调用哪个版本(静态绑定)。
- 虚函数调用:根据实际指向的对象类型决定(动态绑定)。
- 纯虚函数:形如
virtual void func() = 0;,强制子类重写。
以下示例展示了从抽象基类到派生类的覆盖过程:
class Fruit {
public:
// 抽象方法,子类必须实现
virtual void show() = 0;
// 普通虚方法,子类可选重写
virtual void name() {
cout << "Base Name" << endl;
}
};
class Apple : public Fruit {
public:
void show() override {
cout << "This is an Apple" << endl;
}
void name() override {
cout << "Apple Name" << endl;
}
};
int main() {
Apple apple;
apple.show(); // 调用子类重写的纯虚函数
apple.name(); // 调用子类重写的虚函数
return 0;
}
第 5 步:多继承的实现
C++ 允许一个类同时继承多个父类,这在其他主流 OOP 语言中较少见。需注意多重继承可能引发的钻石问题(可通过虚拟继承解决)。
class A { /* ... */ };
class B { /* ... */ };
class C : public A, public B {
// C 同时拥有 A 和 B 的成员
};
二、结构体 struct:数据聚合与对象化的桥梁
在 C++ 中,struct 不仅可以用作 C 风格的数据集合,还可以像类一样包含成员函数、构造函数及访问控制符。它是从 C 过渡到 C++ 面向对象编程的重要过渡形态。
第 1 步:基本定义与初始化
与 class 最大的区别在于:struct 的默认访问权限是 public,而 class 的默认权限是 private。这使得 struct 更适合作为纯数据载体(类似 Java 的 POJO/Bean)。
// 基本结构体定义
struct Book {
string name;
int id;
long ISBN;
} book1, book2; // 可直接在此处定义实例
// 结构体初始化(列表初始化)
Book book3 = {"C++ Primer", 1, 123456789};
第 2 步:结构体的进阶操作
可以使用类型别名简化声明,或使用指针进行内存管理。注意,结构体也可以拥有方法和继承能力。
typedef struct {
int id;
string title;
} Ebook;
// 指针操作
Ebook *ptr = &ebook_instance;
ptr->id = 100;
// 结构体继承
struct SpecialBook : public Book {
string publisher;
void printInfo() { cout << name << endl; };
};
三、共用体 union:内存共享的特殊结构
共用体(Union)是一种特殊的数据类型,其所有成员共享同一段内存空间。这意味着在同一时刻,共用体只能存储其中一个成员的值。对其一成员赋值会破坏其他成员的数据,常用于节省内存或进行底层类型转换。
第 1 步:共用体的定义与行为验证
共用体的大小取决于其最大成员的大小。当写入新成员时,旧成员的二进制数据会被覆盖或reinterpret,因此读取旧成员通常得到无意义值。
union Data {
int i;
double d;
char str[20];
};
int main() {
Data data;
data.i = 10; // 占用4字节整数空间
cout << data.i << endl; // 正常输出
strcpy(data.str, "Hello"); // 现在覆盖了前面的整数
cout << data.str << endl; // 正常输出字符串
// cout << data.i << endl; // 此时读取 i 可能产生错误结果
return 0;
}
第 2 步:共用体的限制与规范
C++ 标准对共用体的限制比 C 更严格,但也赋予了更多功能:
- 访问控制:默认为
public。 - 成员要求:不能包含引用类型成员;不能含有虚函数;不能作为基类被继承。
- 匿名共用体:可以在结构体内定义匿名共用体,使其成员直接暴露在父作用域中,但不能包含受保护(
protected)或私有(private)成员。 - 全局共用体:若为匿名共用体,则必须是
static存储期。
共用体常嵌套在结构中,用于处理互斥的数据场景:
struct Record {
string name;
union {
int score_int;
float score_float;
}; // 匿名共用体
};
四、C 与 C++ 中 Struct 的关键区别
理解这些差异有助于在不同语言环境下正确移植代码:
- 成员函数: C 结构体不能有函数成员;C++ 结构体可以。
- 封装性: C 结构体无访问修饰符;C++ 结构体支持
public/private/protected。 - 继承: C 不支持结构体继承;C++ 结构体支持继承。
- 实例化: C 中定义变量时必须加
struct前缀(如struct Book b);C++ 中可以直接写Book b。
以上就是 C++ 类(class)、结构体(struct)和共用体(union)的详细内容,更多关于 C++ 面向对象编程与内存管理的资料请关注本站其它相关文章!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









