学习日期:2026 年 11 月 10 日 · C++ 基础补强 · 衔接 DirectX 12
本次学习完成了 C++ 面向对象编程的前两讲:
- 第一讲:类、对象、成员变量与成员函数
- 第二讲:访问控制(public/private)与封装
两讲均完成了独立 Coding 实践。下面保留你自己编写的原始代码、存在的问题、修正后的代码,以及相关知识点,方便整理到博客和 GitHub。
第一讲:类与对象(Class & Object)
1. 核心知识点
. 运算符通过对象访问成员screen.ShowResolution()public允许类外部访问成员public:类(Class)是对象的类型定义,对象(Object)是该类型的具体实例。
例如:
Renderer screen;
Renderer 是类名,screen 是对象名。
screen.ShowResolution();
表示通过 screen 对象调用它的 ShowResolution() 成员函数。
2. 我的原始代码
独立完成的第一次类与对象练习
#include <iostream>
using namespace std;
class Renderer
{
public:
int width = 800;
int height = 600;
void ShowResolution()
{
cout << "当前分辨率:" << width
<< "X" << height << endl;
}
void SetResolution(int w, int h)
{
width = w;
height = h;
cout << "当前分辨率:" << width
<< "X" << height << endl;
}
};
int main()
{
Renderer screen;
screen.ShowResolution();
screen.SetResolution(1920, 1080);
return 0;
}
3. 代码检查与纠正
程序可以正确编译运行,基本功能符合要求。
需要优化的是 SetResolution() 的职责。
原代码:
void SetResolution(int w, int h)
{
width = w;
height = h;
cout << "当前分辨率:" << width
<< "X" << height << endl;
}
问题并非语法错误,而是 SetResolution() 同时承担了修改数据和输出数据两项工作,与 ShowResolution() 功能重叠。
修改为:
void SetResolution(int w, int h)
{
width = w;
height = h;
}
然后在 main() 中分别调用设置和显示函数:
screen.SetResolution(1920, 1080);
screen.ShowResolution();
这样各个成员函数的职责更加清晰,也方便以后维护。
4. 修正后的完整代码
#include <iostream>
using namespace std;
class Renderer
{
public:
int width = 800;
int height = 600;
void ShowResolution()
{
cout << "当前分辨率:"
<< width << "x" << height << endl;
}
void SetResolution(int w, int h)
{
width = w;
height = h;
}
};
int main()
{
Renderer screen;
screen.ShowResolution();
screen.SetResolution(1920, 1080);
screen.ShowResolution();
return 0;
}
运行结果:
当前分辨率:800x600
当前分辨率:1920x1080
5. 第一讲总结
关键理解:成员函数能够访问所属对象的成员变量。
例如:
void SetResolution(int w, int h)
{
width = w;
height = h;
}
w 和 h 是函数参数,只在函数调用期间提供数据。
width 和 height 是对象的成员变量,函数执行完成后,修改后的值仍然保存在对象中。
这也是为什么第二次调用 ShowResolution() 时,可以得到 1920x1080。
第二讲:访问控制与封装(Encapsulation)
1. 核心知识点
这一讲主要学习如何控制类中成员的访问权限。
例如:
class GPU
{
private:
int temperature = 40;
public:
void SetTemperature(int t)
{
temperature = t;
}
};
由于 temperature 是私有成员,外部不能直接写:
gpu.temperature = 80; // 编译错误
而应该通过公有成员函数:
gpu.SetTemperature(80); // 正确
这种设计让类能够控制内部数据的修改方式。例如可以增加温度范围检查,拒绝不合理的数据。
这体现了封装:把数据及操作数据的方法组织在类中,并通过访问控制维护对象的内部状态。
2. 我的原始代码
独立完成的 private/public 与条件判断练习
#include <iostream>
using namespace std;
class GPU
{
private:
int memory = 8;
int teletemperature = 40;
public:
void ShowStatus()
{
cout << "显存:" << memory
<< "GB,温度:" << teletemperature
<< "GB";
}
void SetTemperature(int t)
{
if (t > 0 && t < 120)
{
teletemperature = t;
}
else
{
cout << "温度设置无效!" << endl;
}
}
};
int main()
{
GPU gpu1;
gpu1.ShowStatus();
gpu1.SetTemperature(85);
gpu1.ShowStatus();
gpu1.SetTemperature(130);
gpu1.ShowStatus();
return 0;
}
3. 代码检查与纠正
这次练习已经正确使用了 private、public、成员函数和 if/else 条件判断,主要有三个问题。
问题一:温度边界判断不正确。
原代码:
if (t > 0 && t < 120)
题目要求范围为 0~120,包含两个端点。
因此应该修改为:
if (t >= 0 && t <= 120)
两者区别:
这里暴露的问题与此前的循环边界错误相似:需要特别注意题目中的范围是否包含端点。
问题二:输出单位错误且缺少换行。
原代码:
cout << "显存:" << memory
<< "GB,温度:" << teletemperature
<< "GB";
温度不应该使用 GB,并且应该增加换行,避免连续输出粘连。
修改为:
cout << "显存:" << memory
<< "GB,温度:" << temperature
<< "C" << endl;
问题三:变量名不够简洁。
原代码使用:
int teletemperature = 40;
虽然不影响语法,但推荐改成:
int temperature = 40;
这样更符合常见的 C++ 命名习惯,可读性也更好。
另外,你使用 130 测试非法温度,而题目要求的是 150。两者都超出了合法范围,能够达到相同的测试目的,因此不算逻辑错误。
4. 修正后的完整代码
#include <iostream>
using namespace std;
class GPU
{
private:
int memory = 8;
int temperature = 40;
public:
void ShowStatus()
{
cout << "显存:" << memory
<< "GB,温度:" << temperature
<< "C" << endl;
}
void SetTemperature(int t)
{
if (t >= 0 && t <= 120)
{
temperature = t;
}
else
{
cout << "温度设置无效!" << endl;
}
}
};
int main()
{
GPU gpu1;
gpu1.ShowStatus();
gpu1.SetTemperature(85);
gpu1.ShowStatus();
gpu1.SetTemperature(130);
gpu1.ShowStatus();
return 0;
}
运行结果:
显存:8GB,温度:40C
显存:8GB,温度:85C
温度设置无效!
显存:8GB,温度:85C
5. 第二讲总结
这节课最重要的是理解:
GPU gpu1;
gpu1.SetTemperature(85);
程序首先创建 gpu1 对象,然后调用其公有成员函数。
函数内部:
if (t >= 0 && t <= 120)
{
temperature = t;
}
先检查参数,确认数据有效后才修改对象内部的私有变量。
如果传入 130,判断不成立,temperature 不会被修改,仍然保持为 85。
因此,封装不仅仅是把成员设成 private,更重要的是通过成员函数控制数据的访问和修改。
三、两讲知识点综合整理
class 定义类已完成实践创建类对象已完成实践成员变量与成员函数已完成实践. 访问对象成员已完成实践public/private已完成实践通过成员函数修改私有数据已完成实践参数合法性检查已完成实践边界条件判断需要继续强化函数职责划分需要逐步培养对象指针和 ->已完成实践四、与 DirectX 12 的联系
现在回头看你之前不理解的代码:
ComPtr<IDXGIFactory6> factory;
factory->EnumAdapterByGpuPreference(...);
虽然你还没有完全掌握 COM,但已经可以建立一部分联系:
- 你自己写的
GPU和Renderer是类。 gpu1、screen是对象。ShowStatus()、SetResolution()是成员函数。- DX12 的
IDXGIFactory6是 COM 接口类型,它规定了可以调用的成员函数。 EnumAdapterByGpuPreference()是这个接口提供的成员函数。factory是管理该接口指针的ComPtr对象。
目前最大的知识缺口是:为什么普通对象使用 .,而 DX12 的接口调用经常使用 ->。
这正是下一讲需要解决的问题。
五、本次学习结论
第 1 讲与第 2 讲 Coding 练习均已完成。
这两次练习表明,你已经能够独立编写简单的 C++ 类,并使用成员函数操作对象内部的数据。
目前最值得继续加强的是边界条件、输出细节和函数职责划分。这些问题可以通过后续 Coding 训练逐渐改善,不需要因此停止新知识的学习。
下一讲:C++ 面向对象第 3 讲——对象指针与 .、-> 运算符。
届时会从你熟悉的普通指针 int* p 开始,逐步过渡到对象指针 GPU* p,再解释为什么 DX12 会大量出现 factory->... 这样的代码。