C++从入门到实战(五)类和对象(第一部分)为什么有类,及怎么使用类,类域概念详解(附带图谱等更好对比理解)

发布于:2025-03-22 ⋅ 阅读:(26) ⋅ 点赞:(0)


前言

  • 在上一篇博客中,我们深入探讨了 C++ 中几个重要特性:C++ 引用、inline 关键字以及 nullptr

我的个人主页,欢迎来阅读我的其他文章
https://blog.csdn.net/2402_83322742?spm=1011.2415.3001.5343
我的C++知识文章专栏
欢迎来阅读指出不足
https://blog.csdn.net/2402_83322742/category_12880513.html?spm=1001.2014.3001.5482

上一篇博客地址与摘要

https://blog.csdn.net/2402_83322742/article/details/145622425?spm=1001.2014.3001.5501

C++ 引用让我们可以为变量取别名,提高了代码的简洁性和安全性;inline 关键字通过在编译时将函数调用处用函数体替换,减少了函数调用开销;nullptr 则避免了与 0 或 NULL 相关的二义性问题。通过掌握这些特性,我们能够编写出更具灵活性和高效性的代码。

这一篇,我们将继续探索 C++ 中另外几个重要的知识点:类和对象(上)。这些内容将进一步丰富我们对 C++ 语言的理解,为编写更加复杂和高效的程序提供有力支持


一、为什么要有类?类的好处

  • 想象你要管理一家宠物店,店里有很多宠物,每只宠物都有自己的信息(像名字、年龄、品种)和行为(吃东西、睡觉)。
  • 在编程里,如果没有类,这些信息和行为就会乱成一团,很难管理。而类就像是一个 “模板”,可以把宠物的信息和行为组织在一起。有了这个模板,你就能轻松地创建出很多只宠物,并且方便地对它们进行操作

在这里插入图片描述

  • 类的简单代码,后面会详细讲类的知识现在看一下就好
#include <iostream>

// 定义 Rectangle 类
class Rectangle {
private:
    // 私有成员变量,分别表示矩形的长和宽
    double length;
    double width;

public:
    // 构造函数,用于初始化矩形的长和宽
    Rectangle(double l, double w) {
        length = l;
        width = w;
    }

    // 成员函数,用于计算矩形的面积
    double getArea() {
        return length * width;
    }

    // 成员函数,用于计算矩形的周长
    double getPerimeter() {
        return 2 * (length + width);
    }
};

int main() {
    // 创建一个 Rectangle 对象,长为 5,宽为 3
    Rectangle rect(5, 3);

    // 调用成员函数计算并输出矩形的面积和周长
    std::cout << "矩形的面积是: " << rect.getArea() << std::endl;
    std::cout << "矩形的周长是: " << rect.getPerimeter() << std::endl;

    return 0;
}

(一).与 C 语言对比类的作用

1.1 数据和操作的组织方式

C 语言数据和操作是分开的。比如你要处理宠物信息,数据(像宠物的名字、年龄)是单独存储的,操作(像打印宠物信息)也是单独的函数。这样一来,当数据和操作越来越多的时候,代码就会变得很混乱,很难管理。
C++ 类把数据和操作捆绑在一起。你只需要关注这个 “宠物类”,里面的数据和操作都已经组织好了,使用起来非常方便。

1.2 代码复用性

C 语言如果要复用代码,通常需要复制粘贴,然后再进行修改。这样不仅麻烦,还容易出错。
C++ 类通过继承和多态等特性可以轻松地复用代码。比如你已经有了一个 “宠物类”,现在要创建一个 “猫类”,只需要让 “猫类” 继承 “宠物类”,再添加一些猫特有的信息和行为就可以了。

1.3. 安全性

C 语言数据是公开的,任何地方的代码都可以直接访问和修改数据,容易导致数据被意外修改,引发错误。
C++ 类可以通过访问控制符(如private、protected)来限制外部代码对数据的访问,提高了数据的安全性。

(二).类的好处

1数据和操作捆绑

类能把数据(比如宠物的名字、年龄)和操作这些数据的函数(比如给宠物喂食、让宠物睡觉)放在一起。这样做就好像把宠物的所有相关信息和行为都装在一个 “袋子” 里,方便携带和管理。

2. 方便复用代码

当你创建了一个宠物类后,就可以用这个类创建出很多不同的宠物对象。每个宠物对象都继承了类里定义的信息和行为,不需要每次都重新编写相同的代码。就好比你有了一个制作宠物的 “模具”,可以用它做出很多不同的宠物。

3. 增强安全性

类可以控制外部代码对内部数据的访问。你可以决定哪些数据和函数是可以被外部访问的,哪些是只能在类内部使用的。这就像给你的宠物店加上了一些 “门锁”,保护了宠物的隐私和安全。

4. 让代码更有条理

类可以把不同功能的代码分开,每个类负责自己的事情。这样,当你要修改某个功能时,只需要修改对应的类,不会影响到其他部分的代码。就像宠物店被分成了不同的区域,每个区域负责不同的工作,管理起来更加轻松。

二、类的定义

(一)类定义格式

  • 在 C++ 中,class 是定义类的关键字。以下是一个简单的类定义示例:
#include <iostream>
#include <string>

// 定义一个名为 Person 的类
class Person 
{
private:
    // 私有成员变量,存储人名
    std::string name;

public:
    // 构造函数,用于初始化 name 成员变量
    Person(const std::string& n) : name(n) {} 
    //构造函数,后面会详细讲

    // 公有成员函数,用于输出该人的介绍信息
    void introduce() 
    {
        std::cout << "Hello, my name is " << name << "." << std::endl;
    }
};

int main() 
{
    // 创建一个 Person 类的对象,名字为 "Alice"
    Person alice("Alice");

    // 调用 introduce 成员函数,输出介绍信息
    alice.introduce();

    return 0;
}

下面对这段 C++ 代码的详细讲解

class Person 
{
private:
    std::string name;

public:
    Person(const std::string& n) : name(n) {} 
    void introduce() 
    {
        std::cout << "Hello, my name is " << name << "." << std::endl;
    }
};

class Person:使用 class 关键字声明了一个名为 Person 的类。
类是一种用户自定义的数据类型,它可以封装数据(成员变量)和操作这些数据的函数(成员函数)。
私有成员变量

private:
    std::string name;

private 是访问修饰符,它表示在其下面声明的成员(变量或函数)只能在类的内部被访问,外部代码无法直接访问这些私有成员。

公有成员函数

void introduce() 
{
    std::cout << "Hello, my name is " << name << "." << std::endl;
}

introduce() 是一个公有成员函数,外部代码可以通过 Person 类的对象来调用这个函数。

(二)访问限定符

  • 在 C++ 里,类是实现封装的一种方式,它把对象的属性和方法整合在一起,让对象功能更完善,还能通过访问权限控制对外提供的接口。

2.1封装、方法、属性和对象概念名词解释

  • 封装是面向对象编程中的一个重要概念,它指的是将数据(属性)和操作数据的函数(方法)组合在一起,形成一个独立的单元(即类)。

封装的目的是隐藏内部实现细节,只通过类的接口(即公开的方法)与外部交互。

  • 如下面的代码
class BankAccount {
private:
    double balance; // 属性,隐藏在类内部

public:
    void deposit(double amount); // 方法,提供接口
    void withdraw(double amount); // 方法,提供接口
    double getBalance() const; // 方法,提供接口
};

  • 方法
  • 方法是类中定义的函数,用于实现对类属性的操作或完成特定的功能。方法可以访问类的属性,并且可以根据需要对外提供接口。
  • 例如
void BankAccount::deposit(double amount) {
    if (amount > 0) {
        balance += amount;
    }
}

  • 属性
  • 属性是类中定义的变量,用于存储类的状态或数据。
private:
    double balance; // 属性,用于存储账户余额

  • 对象
  • 对象是类的实例,是类的具体表现形式。
  • 通过对象,可以访问类的属性和方法。
  • 例如
BankAccount myAccount; // 创建一个对象
myAccount.deposit(100.0); // 调用对象的方法
double currentBalance = myAccount.getBalance(); // 调用对象的方法

这些概念共同构成了面向对象编程的基础,使得代码更加模块化、可维护和可扩展。

2.2 访问限定符public,private与protected

  • 在 C++ 里,public、private 和 protected 这些访问限定符就像是房屋的不同区域,它们决定了谁能进入以及可以做什么
public(公共区域)
  • 这就好比房屋的公共区域,像客厅、走廊,任何人都能自由进出,想做什么都可以。在 C++ 类里,public 成员可以在类的外部直接被访问,也就是不管在什么地方,只要能接触到这个类的对象,就可以使用这些成员。
private(私人区域)
  • 这类似于房屋的卧室只有房屋主人才能进去。在 C++ 里,private 成员只能在类的内部被访问,类的外部没办法直接使用这些成员。这是一种保护机制,能防止外部随意修改或访问类的关键数据。
protected(受保护区域)
  • 这就像是房屋里孩子的房间,除了主人之外,孩子也能进去。在 C++ 中,protected 成员和 private 成员类似,在类外部不能直接访问,但在该类的子类中可以访问。也就是说,protected 成员可以在类的家族内部使用。
# include <iostream>
using namespace std;
class House
{
public:
	void showLivingRoom() {
		cout << "Welcome to the living room!" << endl;
	}
	

private:
	void showBedroom() {
		cout << "This is the bedroom, you can't enter!" << endl;
	}
protected:
	// 受保护区域,类内部和子类能访问
	void showKidsRoom() {
		cout << "This is the kids' room." << endl;
	}
};

int main() {
	House myHouse;
	myHouse.showLivingRoom(); // 可以访问,因为是 public 成员

	// myHouse.showBedroom(); // 错误,不能访问 private 成员
	// myHouse.showKidsRoom(); // 错误,不能访问 protected 成员

	return 0;
}

在这里插入图片描述

三、类域

在这里插入图片描述

3.1 类域的概念
  • 类定义了⼀个新的作⽤域,类的所有成员都在类的作⽤域中,在类体外定义成员时,需要使⽤::作⽤域操作符指明成员属于哪个类域。

我们简单讲下这段话

  • 类域可以理解成一个 “专属地盘”,每个类都有自己独立的类域
  • 就好像每个国家都有自己的领土范围一样。类里的所有成员(包括成员变量和成员函数)都处在这个类域当中。
  • 在类的内部,你可以直接使用类的成员,因为编译器知道你是在这个类的 “地盘” 里活动。但当你要在类的外部定义成员函数时,就得通过 :: 作用域操作符来明确指出这个成员函数属于哪个类的 “地盘”。
#include <iostream>

// 定义一个名为 Stack 的类
class Stack {
public:
    // 声明一个成员函数 Init
    void Init();

private:
    // 声明一个成员变量 array
    int array[100];
};

// 在类体外定义成员函数 Init,使用 :: 指明属于 Stack 类域
void Stack::Init() {
    // 在成员函数里可以使用类的成员变量 array
    for (int i = 0; i < 100; ++i) {
        array[i] = 0;
    }
    std::cout << "Stack initialized." << std::endl;
}

int main() {
    Stack myStack;
    // 调用 Init 成员函数
    myStack.Init();
    return 0;
}

在这里插入图片描述

  • 在这个代码里,Stack 类有自己的类域。
  • Init 函数在类里只是声明,在类外定义时,使用 Stack::Init() 明确指出 Init 是 Stack 类的成员函数。
  • 在 Init 函数里使用 array 成员变量时,编译器就会到 Stack 类域里去查找 array 的定义。
  • 要是不指定 Stack::,编译器就会把 Init 当成全局函数,在全局作用域里找不到 array 的定义,就会报错。

总结 核心概念速记 :

核心概念速记

类与对象核心 = 封装三要素 + 访问控制 + 类域作用

  • 封装三要素
    • 属性(成员变量) → 方法(成员函数) → 访问控制(public/private/protected)
  • 类域规则
    • 成员默认访问权限:class默认为privatestruct默认为public
    • 类外定义成员需用::作用域操作符

知识对比表格

C语言 vs C++类的特性对比

维度 C语言 C++类
数据组织 数据与函数分离 数据(属性)与函数(方法)捆绑
代码复用 复制粘贴修改 继承/多态/模板
安全性 数据全局可见 访问控制符(private/protected)
扩展性 函数参数扩展复杂 类成员增减灵活

类的成员访问控制

访问限定符对比表

限定符 类内访问 类外访问 子类访问 典型用途
public ✔️ ✔️ ✔️ 对外接口(如show()
private ✔️ 私有数据(如balance
protected ✔️ ✔️ 子类继承数据

类域与作用域操作符

类域作用示意图

全局作用域  
├─ 类作用域(Stack)  
│  ├─ public: Init()  
│  └─ private: array[100]  
└─ main()  
   └─ Stack myStack; → 访问类域成员

关键代码示例

class Stack {
public:
    void Init(); // 声明在类域
};

// 类外定义需指定类域
void Stack::Init() { 
    array[0] = 0; // 编译器到Stack类域查找array
}

知识图谱

类和对象(上)  
├─ 类的定义  
│  ├─ 语法结构:class关键字 + 成员列表  
│  ├─ 成员类型:属性(变量)+ 方法(函数)  
│  └─ 默认访问:class→private,struct→public  
├─ 访问控制  
│  ├─ public(公共接口)  
│  ├─ private(类内私有)  
│  └─ protected(子类可用)  
├─ 类域规则  
│  ├─ 作用域操作符`::`  
│  └─ 编译查找顺序:当前域→类域  
└─ 类的优势  
   ├─ 封装性 → 数据安全  
   ├─ 复用性 → 代码重用  
   └─ 模块化 → 结构清晰  

重点提炼

  1. 类的本质

    • 自定义数据类型,捆绑数据与操作,实现封装的核心载体
  2. 访问控制黄金法则

    • 成员变量尽量private对外接口用public继承相关用protected
  3. 类域核心作用

    • 解决命名冲突,明确成员归属,编译时通过::定位作用域
  4. 与C语言的本质区别

    • 面向过程(C) vs 面向对象(C++),类是OOP的基础

常见问题与误区

Q1:类的成员函数必须在类内定义吗?

  • A:不必。可在类内声明,类外通过::定义,提高代码可读性

Q2:structclass有什么区别?

  • A:唯一区别是默认访问权限struct默认publicclass默认private

Q3:为什么成员变量要设为private

  • A:防止外部直接修改,通过public方法控制读写逻辑(如校验数据合法性)

技术演进脉络

C语言结构体 → C++类 → 继承 → 多态 → 模板  
   ↓          ↓           ↓       ↓       ↓  
数据聚合 → 数据+操作 → 代码复用 → 动态绑定 → 泛型编程  

以上就是这篇博客的全部内容,下一篇我们将继续探索更多精彩内容。

我的个人主页,欢迎来阅读我的其他文章
https://blog.csdn.net/2402_83322742?spm=1011.2415.3001.5343
我的C++知识文章专栏
欢迎来阅读指出不足
https://blog.csdn.net/2402_83322742/category_12880513.html?spm=1001.2014.3001.5482

非常感谢您的阅读,喜欢的话记得三连哦

在这里插入图片描述