本篇核心知识:预处理指令、宏定义、条件编译、文件包含、C++ 面向对象、类与对象、访问权限、成员函数、this 指针、const 成员、头文件管理、内联函数、封装特性
一、预处理指令(编译前执行)
概念
预处理指令以#开头,编译前执行,不生成机器码,只做文本替换、文件包含、条件控制。
特性
-
预处理时机:编译之前,语法检查之前,直接替换文本。
-
三大核心指令 :
#define、#include、条件编译。
(1)#define 宏定义
概念
用名字替换固定文本,分无参宏 、带参宏,仅替换、无类型、无语法检查。
特性
-
无参宏:
#define 宏名 替换内容-
纯文本替换,末尾不加分号。
-
可定义常量、关键字、代码片段。
-
-
带参宏:
#define 宏名(参数) 表达式-
仅替换,不是函数,无类型检查、执行更快。
-
表达式建议加括号防优先级错误。
-
-
多行宏 :末尾用
\换行,不可空格。 -
宏 undef :
#undef 宏名取消宏定义。
代码示例
// 无参宏
#define MAX 100
#define PI 3.14159
#define PRINT_HELLO cout << "Hello\n"
// 带参宏(加括号防错)
#define SQR(x) ((x)*(x))
#define MAX2(a,b) ((a)>(b)?(a):(b))
// 多行宏
#define PRINT_INFO() \
cout << "姓名:张三\n"; \
cout << "年龄:20\n"
int main() {
int a = SQR(5); // 替换为((5)*(5))
PRINT_HELLO;
PRINT_INFO();
return 0;
}
(2)#include 文件包含
概念
将头文件内容完整复制到当前位置,实现代码复用。
特性
-
#include <文件名>:优先查系统库目录,用于系统头文件。
-
#include "文件名":先查当前项目目录,再查系统目录,用于自定义头文件。
-
重复包含问题:同一头文件多次包含会报错,需加保护。
代码示例
// 系统头文件
#include <iostream>
// 自定义头文件
#include "myhead.h"
(3)条件编译
概念
按条件选择性编译代码,常用于调试、版本控制、跨平台、防重复包含。
特性
-
#if / #elif / #else / #endif:按常量表达式判断。
-
#ifdef:如果宏已定义。
-
#ifndef:如果宏未定义。
-
#endif :结束条件块,必须配对。
-
防重复包含:
#ifndef HEAD_H #define HEAD_H // 头文件内容 #endif // 或简化:#pragma once(VS支持)
代码示例
#define DEBUG
// 调试模式输出
#ifdef DEBUG
cout << "调试:变量值=" << 10 << endl;
#else
cout << "发布模式" << endl;
#endif
// 版本控制
#define VERSION 2
#if VERSION == 1
cout << "V1.0" << endl;
#elif VERSION == 2
cout << "V2.0" << endl;
#else
cout << "未知版本" << endl;
#endif
拓展:宏与函数区别
-
宏:编译前替换、无类型、速度快、无栈开销、易出错。
-
函数:编译后调用、有类型、有栈开销、安全、可调试。
二、C++ 面向对象(OOP)基础
概念
面向对象以类(模板) 和对象(实例) 为核心,将数据和行为封装,模拟现实实体,具备**封装、继承、多态(、抽象)**几大特性。
特性
-
面向对象 vs 面向过程
-
面向过程:关注步骤、函数、流程,适合简单程序。
-
面向对象:关注实体、属性、行为,适合复杂项目、易维护复用。
-
-
四大特性
-
封装:隐藏内部细节,暴露安全接口,保证数据安全。
-
继承:子类复用父类代码,扩展功能,减少冗余。
-
多态:同一接口,不同实现,灵活扩展。
-
抽象:提取核心属性 / 行为,忽略无关细节。
-
代码示例
// 面向对象:定义人类(类)
class Person {
// 属性:成员变量(私有)
char name[20];
int age;
public:
// 行为:成员函数(公有)
void init(const char* n, int a) {
strcpy(name, n);
age = a;
}
void show() {
cout << "姓名:" << name << ",年龄:" << age << endl;
}
};
// 创建对象(实例)
int main() {
Person p1;
p1.init("张三", 20);
p1.show();
return 0;
}
三、类的定义与结构
概念
类是自定义复合类型,描述一组对象共同的属性和行为。
特性
-
类的组成
-
成员变量(属性):描述对象状态。
-
成员函数(行为):描述对象操作。
-
访问权限:控制成员访问范围。
-
-
定义格式
class 类名 { // 访问权限 成员变量; 成员函数声明; }; // 末尾必须加分号 -
对象定义 :
类名 对象名;,分配独立内存。
代码示例
// 类定义
class Student {
private:
// 私有成员变量
int id;
double score;
public:
// 成员函数声明
void setInfo(int i, double s);
void showInfo();
};
// 定义对象
Student s1, s2;
四、访问权限控制(封装核心)
概念
控制类成员的可见范围,实现数据隐藏、安全访问。
特性
-
public(公有):任意位置(类内、外、子类)可访问,用于接口。
-
protected(保护):类内、子类可访问,外部不可,用于继承。
-
private(私有):仅类内可访问,外部、子类不可,用于隐藏数据。
-
默认权限 :
class默认 private,struct默认 public。
代码示例
class Person {
private:
int age; // 私有:外部不可直接访问
protected:
char gender; // 保护:子类可访问
public:
char name; // 公有:任意访问
void setAge(int a) { age = a; } // 公有接口
};
int main() {
Person p;
p.name = "李四"; // 合法(公有)
// p.age = 25; // 非法(私有)
p.setAge(25); // 合法(通过接口)
return 0;
}
拓展:权限设计原则
- 数据成员默认 private,通过 public 接口访问修改,保证数据安全。
五、成员函数(定义与实现)
概念
类中描述对象行为的函数,分内部实现 、外部实现。
特性
-
内部实现 :直接写在类内,默认内联函数,编译时展开,无调用开销。
-
外部实现:类内声明、类外定义,需加
作用域符::,格式:
返回值 类名::函数名(参数) { 函数体 } -
内联函数 :
inline修饰,空间换时间,适合短小高频函数。
代码示例
class Student {
private:
int id;
public:
// 内部实现(默认内联)
inline void setId(int i) { id = i; }
// 外部声明
void showId();
};
// 外部实现(加::)
void Student::showId() {
cout << "学号:" << id << endl;
}
拓展:内联函数注意
- 禁止递归、复杂循环,编译器可能忽略
inline。
六、this 指针
概念
类成员函数的隐藏常量指针,指向当前调用对象,区分不同对象成员。
特性
-
类型 :
类名* const,指向不可改,值可改。 -
作用:
-
区分成员变量与局部 / 形参(同名冲突)。
-
返回当前对象(链式调用)。
-
-
使用 :
this->成员名访问成员。
代码示例
class Person {
private:
int age;
public:
void setAge(int age) {
// this->age:成员变量;age:形参
this->age = age;
}
Person& getSelf() {
return *this; // 返回当前对象
}
};
拓展:this 不能用于静态成员函数(无对象)
七、const 成员(只读保护)
概念
用const修饰成员变量、成员函数、对象,禁止修改,保证数据只读。
特性
-
const 成员变量 :类内只读,必须初始化(构造函数初始化列表)。
-
const 成员函数:
-
格式:
返回值 函数名() const -
禁止修改成员变量,只能调用 const 函数。
-
-
const 对象 :
const 类名 对象,只能调用 const 成员函数,不可调用非 const 成员函数。 -
普通对象(无 const) :既能调用 普通函数,也能调用 const 成员函数,优先调用非 const 版本。
代码示例
class Test {
public:
int num = 10;
// const 成员函数
void show() const {
cout << "const 函数:" << num << endl;
}
// 非 const 成员函数
void show() {
cout << "非 const 函数:" << num << endl;
}
};
int main() {
// 1. 普通对象(无const)
Test obj;
obj.show(); // 调用 非const 函数
obj.show(); // 也能调用 const 函数(普通对象全能调用)
// 2. const 对象
const Test cobj;
cobj.show(); // 只能调用 const 函数
//cobj.show();// 不能调用 非const 函数
}
拓展:const 修饰指针 / 引用
-
const int*:指向常量,值不可改。 -
int* const:指针常量,指向不可改。
八、头文件与源文件分离
概念
大型项目中,类声明放.h头文件,实现放.cpp源文件,便于管理、复用、编译。
特性
-
头文件(.h) :类声明、函数声明、宏、全局声明,只声明不定义。
-
源文件(.cpp):类实现、函数定义、全局定义。
-
头文件保护 :防止重复包含,用
#ifndef...#endif或#pragma once。
代码示例
// Person.h(头文件)
#pragma once
class Person {
private:
char name[20];
public:
void setName(const char* n);
void showName() const;
};
// Person.cpp(源文件)
#include "Person.h"
#include <cstring>
void Person::setName(const char* n) { // 声明外部实现
strcpy(name, n);
}
void Person::showName() const {
cout << "姓名:" << name << endl;
}
// main.cpp
#include "Person.h"
int main() {
Person p;
p.setName("XXX");
p.showName();
return 0;
}
九、结构体 vs 类(对比)
概念
结构体(struct)和类(class)都是复合类型,默认权限不同。
特性
-
struct :默认public,仅数据,早期 C 风格。
-
class :默认private,数据 + 函数,面向对象。
-
本质:C++ 中 struct 可写成员函数,与 class 语法一致。
代码示例
// struct:默认public
struct Stu {
int id;
void show() { cout << id; }
};
// class:默认private
class StuC {
int id;
public:
void show() { cout << id; }
};