一、类结构设计示例
1.1 Point 点类
// ====================== Point 点类 ====================== class Point { private: float x; // x坐标 float y; // y坐标 public: // 1. 无参构造函数:默认 (0, 0) Point() { x = 0; y = 0; } // 2. 带参构造函数:自定义坐标 Point(float xVal, float yVal) { x = xVal; y = yVal; } // 设置x、y void setX(float xVal) { x = xVal; } void setY(float yVal) { y = yVal; } // 获取x、y(常成员函数) float getX() const { return x; } float getY() const { return y; } // 打印坐标点 void print() const { cout << "(" << x << ", " << y << ")"; } };1.2 Line 线段类
// ====================== Line 线段类 ====================== class Line { private: Point a; // 起点 Point b; // 终点 public: // 1. 无参构造:两个点都默认为 (0,0) Line() { // a 和 b 自动调用 Point 的无参构造 } // 2. 带参构造:直接传入四个坐标值 Line(float x1, float y1, float x2, float y2) : a(x1, y1), b(x2, y2) // 初始化列表给 a、b 赋值 { } // 设置起点、终点 void setA(Point p) { a = p; } void setB(Point p) { b = p; } // 获取起点、终点 Point getA() const { return a; } Point getB() const { return b; } // 核心:计算线段长度 float getLength() const { float dx = a.getX() - b.getX(); float dy = a.getY() - b.getY(); return sqrt(dx * dx + dy * dy); } // 打印线段信息 void printLine() const { cout << "线段起点:"; a.print(); cout << " 终点:"; b.print(); cout << " 长度:" << getLength() << endl; } };1.3 CDate 日期类
class CDate { private: int year; int month; int day; public: //无参构造:初始化列表 CDate() :year(1), month(1), day(1) {} //带参构造 CDate(int y, int m, int d) :year(y), month(m), day(d) {} //常成员打印 void PrintDate() const { printf("%4d/%02d/%02d\n", year, month, day); } };1.4 Complex 复数类
class Complex { private: double real; double image; public: //设置成员 void setReal(double r) { this->real = r; } void setImage(double i) { this->image = i; } //常成员函数取值 double getReal() const { return this->real; } double getImage() const { return this->image; } //打印复数 void PrintInfo() const { cout << "(" << real << (image >= 0 ? "+" : "") << image << "i)" << endl; } //加法1:值传递参数 Complex Add(Complex c) { Complex tmp; tmp.real = this->real + c.real; tmp.image = this->image + c.image; return tmp; } //加法2:const引用参数+const成员 Complex Add(const Complex& c) const { Complex tmp; tmp.real = this->real + c.real; tmp.image = this->image + c.image; return tmp; } //运算符重载 + Complex operator+(const Complex& c) const { Complex tmp; tmp.real = this->real + c.real; tmp.image = this->image + c.image; return tmp; } };二、类与对象内存模型(引出 this 指针)
2.1 内存节省原理
所有同类对象共用一份成员函数代码,每个对象只独立存储私有数据成员,避免每个对象复制函数造成内存浪费。
2.2 关键疑问
共用代码如何区分不同对象的数据?
编译器自动给非静态成员函数添加隐藏形参this 指针,调用时自动传入当前对象地址。
2.3 编译转换示例
c1.setReal(1.2) → 编译转换:setReal(&c1, 1.2) c2.setReal(3.4) → 编译转换:setReal(&c2, 3.4) // 函数内 real = r 等价 this->real = r三、this 指针详解
3.1 this 基础属性
- 存在范围:仅非静态成员函数自带隐式 this,全局函数、静态成员函数、友元无 this。
- 指针类型:
- 普通成员函数:
类名* const this - const 修饰成员函数:
const 类名* const this
- 普通成员函数:
*const this:指针本身地址不可修改(不能 this=NULL)const 类名*:不能通过 this 修改对象成员(常成员函数只读)- 不能手动声明 this,由编译器自动生成。
3.2 const 成员函数(this 被 const 修饰)
- 语法:函数括号后加 const,例:
double getReal() const; - 约束:const 成员函数不能修改对象的任何非静态成员变量(mutable 修饰的除外)。
- 调用权限:const 对象只能调用 const 成员函数;非 const 对象可以调用 const 和非 const 成员函数。
- 重载规则:const 和非 const 版本可以构成重载,编译器根据调用对象的 const 性质选择。
3.3 this 指针的应用场景
- 区分同名成员:当形参名与成员变量名相同时,使用 this-> 明确指定成员变量。
- 返回对象自身:实现链式调用,如
return *this;。 - 在成员函数中调用其他成员函数:通过 this 指针传递当前对象。
四、测试代码示例
4.1 Point 和 Line 测试
int main() { // 测试 Point Point p1(1, 1); Point p2(4, 5); cout << "===== 点信息 =====" << endl; p1.print(); cout << endl; p2.print(); cout << endl; // 测试 Line Line line1(p1.getX(), p1.getY(), p2.getX(), p2.getY()); Line line2(0, 0, 3, 4); cout << "\n===== 线段信息 =====" << endl; line1.printLine(); line2.printLine(); return 0; }4.2 CDate 测试
int main() { CDate dt1; //默认1/1/1 CDate dt2(2025, 7, 24);//自定义日期 dt1.PrintDate(); dt2.PrintDate(); return 0; }4.3 Complex 测试
int main() { Complex c1, c2, c3; c1.setReal(1.2); c1.setImage(3.4); c2.setReal(3.4); c2.setImage(5.6); c1.PrintInfo(); c2.PrintInfo(); //重载+调用:c3=c1.operator+(c2) c3 = c1 + c2; c3.PrintInfo();//输出(4.6+9i) return 0; }五、总结
本文通过四个完整的类示例(Point、Line、CDate、Complex)详细讲解了 C++ 类的基本结构设计,重点分析了类与对象的内存模型,并深入剖析了 this 指针的工作原理和 const 成员函数的使用。理解这些概念对于掌握 C++ 面向对象编程至关重要,特别是在考试和实际开发中都会频繁涉及。