前言

在 C++ 编程语言的学习体系中,类(class)是面向对象编程思想的入门基石,也是构建复杂程序逻辑的核心载体。不同于 C 语言仅将结构体作为单纯数据集合的用法,C++ 引入了类的概念,将数据属性与行为方法有机结合,依托访问权限控制实现基础封装特性。

类与结构体既有语法上的相通之处,也存在默认访问权限等关键细节差异,是初学者极易混淆的知识点。本文将从基础概念出发,通俗易懂地讲解 C++ 类与结构体的定义规则、成员构成、访问权限、对象使用及基础构造析构相关内容,帮助学习者理清二者的联系与区别,夯实 C++ 面向对象编程的入门基础。

1. C++的类(class)到底是什么?

1.1 类的本质

类 = 面向对象的核心 = 封装「属性」+「行为」的模板

  • 属性:描述事物的特征(变量),理解为结构体的主要存放对象.
  • 行为:描述事物能做什么(函数),结构体中一般不使用函数.

类本身不是真实数据,用类创建出来的变量叫「对象」.

形象的比喻: 类 == 图纸   对象 == 按图纸盖出来的房子

1.2 类的语法结构

class 类名 
{
    访问权限:
        成员变量(属性)
        成员函数(行为)
};

除了访问权限,类的其它语法部分都与结构体相同.

1.3 类的三大访问权限 (必须掌握)

(1). public 公有

本类内、类外都能访问。

(2). private 私有

只有类自己内部能访问,外部不能直接读写。→ 这就是封装:保护数据不被乱改。

这里唯一一个例外叫友元(friend) : friend 可以打破 private 权限,强行访问私有成员

一句话:friend 就是给外人开特权,让外人能访问我类里的 private 私有成员

这部分先说到这里,有个印象就好,之后详细解释.

(3). protected 保护

类内部 + 子类可以访问,外部不能访问。

1.4 类的基本写法示例

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

class Student {
private:
    // 私有成员变量(外部不能直接改)
    string name;
    int age;

public:
    // 设置信息
    void setInfo(string n, int a) {
        name = n;
        age = a;
    }

    // 显示信息
    void showInfo() {
        cout << "姓名:" << name << endl;
        cout << "年龄:" << age << endl;
    }
};

int main() {
    // 创建对象
    Student s;

    // 调用公有成员函数
    s.setInfo("张三", 18);
    s.showInfo();

    return 0;
}

1.5. 类的四大特殊函数(默认自带)

即使你不写,编译器也会自动生成:(后面出一期详细讲解)

(1). 构造函数:创建对象时自动调用

(2). 析构函数:销毁对象时自动调用

(3). 拷贝构造函数:用对象初始化新对象

(4). 赋值运算符重载:对象之间赋值

2. C++ 类(class)与结构体(struct)的区别(超详细)

一句话总结:

C++ 中 class 和 struct 99% 完全一样,唯一区别是:默认访问权限不同。

2.1 详细对照表

特性 class(类) struct(结构体)
默认访问权限 private(私有) public(公开)
默认继承权限 private 继承 public 继承
能否有成员函数 可以 可以
能否有构造 / 析构 可以 可以
能否继承 可以 可以
能否多态 可以 可以
习惯用途 面向对象封装 纯数据结构

2.2  代码对比

struct 默认 public

struct Student {
    int id; // 默认 public
    string name;
};

int main() {
    Student s;
    s.id = 1; // 可以直接访问
    return 0;
}

class 默认 private

class Student {
    int id; // 默认 private
    string name;
};

int main() {
    Student s;
    // s.id = 1; ❌ 报错,不能访问
    return 0;
}

3. 重要结论

(1). C 语言的 struct 只能存变量,不能有函数。

(2).C++ 的 struct 完全是 class 的翻版,功能几乎相同,只是默认访问权限不同。

(3). 类和结构体都有:成员变量、成员函数、三种访问权限、构造析构函数

(4). 实际开发习惯:类适合封装隐藏数据,结构体适合简单做数据集合。

  • struct:存简单数据(坐标、颜色、顶点)
  • class:封装复杂功能(日志、数据库、网络、算法)

4. 实战: 用类写一个专业级基础日志类(Logger)

首先,我们这里要写的日志功能是:给程序打印 “带时间、带等级、可过滤” 的提示信息,方便程序员看程序运行状态、找错误.

4.1 使用枚举

这里需要表示日志等级,因为INFO, WARN, ERROR等都是同一类型的数据,所以我们使用枚举用来表示【日志等级】,让代码更清晰、更安全、更好维护。

 enum class Level
    {
        INFO = 0,
        WARN = 1,
        ERROR = 2
    };

接下来要创建一个private变量来存放要设置的"我的日志等级",当信息等级大于等于个人设置的日志等级时,信息才会被打印.

4.2 m_loglevel

这里顺便初始化为INFO(最低的等级).

private:
    Level m_logLevel = INFO;

4.3 时间戳

在下面来到最有趣的一个部分:时间戳.

 // 获取当前时间字符串
    string getTime() const
    {
        time_t now = time(nullptr);
        char buf[20];
        strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", localtime(&now));
        return string(buf);
    }

超详细逐行讲解:

(1). time_t now = time(nullptr);

作用:获取从 1970 年 1 月 1 日 到现在一共过了多少秒这叫 Unix 时间戳

例子:现在是 1735976652 秒计算机内部就是用这个数字表示时间。

(2). 2. char buf[20];

作用:开一个字符数组,用来存我们要的格式:

2025-12-19 15:30:45

数一数长度为19 个字符,所以字符数组大小开 20 足够。

(3).strftime(...) 最重要部分!

作用:把数字时间戳 → 人类能看懂的时间字符串

使用语法:

strftime(
    存结果的数组,
    数组大小,
    格式字符串,
    时间结构体
);

格式符号解释:

%Y  年 (2025)
%m  月 (12)
%d  日 (19)
%H  时 (15)
%M  分 (30)
%S  秒 (45)

所以数据从这样:

"%Y-%m-%d %H:%M:%S"

变成这样:

2025-12-19 15:30:45

(4). localtime(&now)

作用:把系统时间秒数→ 转成 年、月、日、时、分、秒 的结构体

(5).return string(buf);

最终输出结果:

[2025-12-19 15:30:45] [INFO] 程序启动成功

把字符数组转成字符串,返回给日志输出使用。

4.4 通用打印函数

 // 通用打印函数
    void print(Level level, const string& levelStr, const char* message)
    {
        if (level >= m_logLevel)
        {
            cout << "[" << getTime() << "] [" << levelStr << "] " << message << endl;
        }
    }

如果在类中写三个不同的打印函数不免显得累赘复杂(我之前就是这么写的haha),所以这里定义一个通用打印函数来满足所有需求.

第一个传入的参数是当前这条日志自己的等级,可以看到下面会与设置的日志等级比较,如果大于等于等级,就会打印信息.

传入的第二个参数是用来在日志里显示 [INFO] / [WARN] / [ERROR] 这些文字标签的.看到输出标签中间的[INFO][WARN][ERROR]就是 第二个参数 levelStr 输出的!

传入的第三个参数是自己输入要显示的信息,在下面接着显示.

4.5 日志等级设置

public:
    void setLogLevel(Level level)
    {
        m_logLevel = level;
    }

这个函数的功能就是传入一个等级,将传入的等级赋给m_loglevel,也就是设置了日志等级.

4.6 三个等级函数

void info(const char* message)
    {
        print(Level::INFO, "INFO", message);
    }

    void warn(const char* message)
    {
        print(Level::WARN, "WARN", message);
    }

    void error(const char* message)
    {
        print(Level::ERROR, "ERROR", message);
    }

4.7 主函数main

int main(void)
{
    Log log;
    // 设置日志等级为 WARN,只会打印 WARN 和 ERROR
    log.setLogLevel(Log::Level::WARN);

    log.info("程序启动成功");   // 等级0 < 1,不打印
    log.warn("内存不足");   // 等级1 >= 1,打印
    log.error("文件打开失败"); // 等级2 >= 1,打印

    return 0;
}

运行结果:

[2026-05-07 20:11:18] [INFO] 程序启动
[2026-05-07 20:11:18] [WARN] 内存不足
[2026-05-07 20:11:18] [ERROR] 文件打开失败

下面附上完整代码:

#include <iostream>
#include <ctime>
#include <string>
using namespace std;
class Log
{
public:
    // 日志等级:数字越大,优先级越高
    enum class Level
    {
        INFO = 0,
        WARN = 1,
        ERROR = 2
    };

private:
    Level m_logLevel = Level::INFO;

    // 获取当前时间字符串
    string getTime() const
    {
       time_t now = time(nullptr);
        char buf[20];
        strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", localtime(&now));
        return std::string(buf);
    }

    // 通用打印函数
    void print(Level level, const std::string& levelStr, const char* message)
    {
        if (level >= m_logLevel)
        {
            std::cout << "[" << getTime() << "] [" << levelStr << "] " << message << std::endl;
        }
    }

public:
    void setLogLevel(Level level)
    {
        m_logLevel = level;
    }

    void info(const char* message)
    {
        print(Level::INFO, "INFO", message);
    }

    void warn(const char* message)
    {
        print(Level::WARN, "WARN", message);
    }

    void error(const char* message)
    {
        print(Level::ERROR, "ERROR", message);
    }
};

int main(void)
{
    Log log;
    // 设置日志等级为 INFO,会打印INFO, WARN 和 ERROR
    log.setLogLevel(Log::Level::INFO);

     log.info("程序启动");
     log.warn("内存不足");
     log.error("文件打开失败");

    return 0;
}

在此不胜感谢能够看到这里的同学,如果发现文章有错误还请不吝赐教.

后续内容会不断更新,感兴趣的同学可以关注点赞收藏慢慢观看.

万分感谢!

-------------------------------------------------------------------------------------------

                                                                                                                         2026.5.18

                                                                                                                           -----22.41

更多推荐