-
二维点的表示(类设计)
- 知识点讲解:
- 封装:将数据成员(
x
和y
坐标)设为private
,这遵循了面向对象编程中的封装原则,防止外部代码随意修改类内部的数据,保证数据的安全性和完整性。只有通过类提供的公有成员函数(getX
、getY
、setX
、setY
)才能访问和修改数据。 - 构造函数:提供了一个带默认参数的构造函数
Point(double _x = 0, double _y = 0)
,这样既可以创建指定坐标的点,也能方便地创建原点。默认参数简化了代码,减少了重载构造函数的数量。 - 访问器与修改器:
getX
、getY
函数被定义为const
,意味着调用它们不会修改类对象的状态,这符合函数的语义,也能让这些函数用于const
对象。setX
和setY
用于更新坐标值。
- 封装:将数据成员(
- 知识点讲解:
-
操作符重载
- 知识点讲解:
- 加法操作符重载:通过
Point operator+(const Point& p1, const Point& p2)
重载+
操作符,这使得代码书写更符合数学直觉,Point
类对象能像内置数据类型一样相加。函数接收两个const
引用参数,避免了不必要的对象复制,提高效率,并且保证传入的对象在函数内不会被修改。 - 输出流操作符重载:
std::ostream& operator<<(std::ostream& os, const Point& p)
重载<<
操作符用于格式化输出Point
对象。返回std::ostream&
类型,以便能连续使用输出操作符,例如cout << p1 << " 和 " << p2
,这遵循了流操作的链式调用风格。
- 加法操作符重载:通过
- 知识点讲解:
-
有理数类设计
- 知识点讲解:
- 数据成员与初始化:
Rational
类有两个数据成员numerator
(分子)和denominator
(分母) 。构造函数Rational(int num = 0, int den = 1)
通过默认参数支持创建整数形式的有理数,同时立即调用simplify
函数对分数进行约分和规范符号,确保有理数始终以最简形式存在。 - 约分与符号处理:
simplify
函数利用std::gcd
(求最大公约数函数,来自<algorithm>
库)对分子分母约分,还会调整分母为正,让有理数的表示更加规范统一。 - 加法操作符重载:
Rational operator+(const Rational& r) const
重载加法操作符,按照分数加法规则计算新的分子分母,再构造并返回新的Rational
对象。函数标记为const
,因为它不会修改调用它的对象状态。
- 数据成员与初始化:
- 知识点讲解:
-
token扫描器类设计
- 知识点讲解:
- 成员变量:
TokenScanner
类有两个关键成员变量,input
存储待扫描的字符串,pos
记录当前扫描位置,它们控制着扫描流程。 - 扫描逻辑:
nextToken
函数通过移动pos
跳过开头的空白字符,然后截取连续的非空白字符段作为一个token
,实现了基本的词法扫描功能。这种逐步移动指针、截取子串的方式是文本处理类常见的做法。 - 状态判断:
hasMoreTokens
函数通过比较pos
和input
的大小,快速判断是否还有剩余未扫描的token
,方便控制循环扫描的流程。
- 成员变量:
- 知识点讲解:
-
将程序封装成类
- 知识点讲解:
- 职责单一:
CircleAreaCalculator
类专注于圆面积的计算这一单一职责,把相关的半径数据和计算逻辑封装在一起。遵循单一职责原则的类更容易维护、测试和扩展。 - 构造函数与初始化:构造函数
CircleAreaCalculator(double r)
接收半径参数初始化radius
,为后续计算面积做准备。这种在构造时初始化关键数据的方式很常见,保证对象创建后处于可用状态。 - 常量成员函数:
calculateArea
函数被定义为const
,因为它只读取radius
的值来计算面积,不修改类的任何成员变量,向调用者表明函数的“只读”特性,同时也允许该函数被const
对象调用。
- 职责单一:
- 知识点讲解:
以下是更详细的代码示例,:
#include <iostream>
#include <algorithm>
#include <string>// 二维点的表示
class Point {
private:double x;double y;
public:// 构造函数,带默认参数Point(double _x = 0, double _y = 0) : x(_x), y(_y) {} // 访问器函数double getX() const { return x; } double getY() const { return y; } // 修改器函数void setX(double newX) { x = newX; } void setY(double newY) { y = newY; }
};// 操作符重载:加法
Point operator+(const Point& p1, const Point& p2) {return Point(p1.getX() + p2.getX(), p1.getY() + p2.getY());
}// 操作符重载:输出流
std::ostream& operator<<(std::ostream& os, const Point& p) {os << "(" << p.getX() << ", " << p.getY() << ")";return os;
}// 有理数类
class Rational {
private:int numerator;int denominator;// 约分和符号处理函数void simplify() {int gcd = std::gcd(numerator, denominator);numerator /= gcd;denominator /= gcd;if (denominator < 0) {numerator = -numerator;denominator = -denominator;}}
public:// 构造函数,带默认参数Rational(int num = 0, int den = 1) : numerator(num), denominator(den) {simplify();} int getNumerator() const { return numerator; }int getDenominator() const { return denominator; }// 加法操作符重载Rational operator+(const Rational& r) const {int newNum = numerator * r.denominator + r.numerator * denominator;int newDen = denominator * r.denominator;return Rational(newNum, newDen);}
};// token扫描器类
class TokenScanner {
private:std::string input;size_t pos;
public:TokenScanner(const std::string& str) : input(str), pos(0) {}std::string nextToken() {while (pos < input.size() && std::isspace(input[pos])) {pos++;}if (pos >= input.size()) {return "";}size_t start = pos;while (pos < input.size() &&!std::isspace(input[pos])) {pos++;}return input.substr(start, pos - start);}bool hasMoreTokens() {return pos < input.size();}
};// 将程序封装成类:圆面积计算器
class CircleAreaCalculator {
private:double radius;
public:CircleAreaCalculator(double r) : radius(r) {}double calculateArea() const {return 3.14 * radius * radius;}
};int main() {// 二维点的使用Point p1(1.0, 2.0);Point p2(3.0, 4.0);Point sum = p1 + p2;std::cout << "p1: " << p1 << ", p2: " << p2 << ", sum: " << sum << std::endl;// 有理数的使用Rational r1(1, 2);Rational r2(1, 3);Rational sumR = r1 + r2;std::cout << r1.getNumerator() << "/" << r1.getDenominator() << " + " << r2.getNumerator() << "/" << r2.getDenominator() << " = " << sumR.getNumerator() << "/" << sumR.getDenominator() << std::endl;// token扫描器的使用std::string test = "hello world";TokenScanner scanner(test);while (scanner.hasMoreTokens()) {std::string token = scanner.nextToken();std::cout << "Token: " << token << std::endl;}// 圆面积计算器的使用CircleAreaCalculator calculator(5.0);double area = calculator.calculateArea();std::cout << "圆的面积: " << area << std::endl;return 0;
}
这段代码整合了多个类的设计与应用,展示了如何通过类来封装数据与功能,以及利用操作符重载让自定义类的使用更加自然流畅,同时还有文本扫描和简单几何计算功能的实现。
- 二维点的表示(类设计)
- 类的定义
- 首先,定义一个
Point
类来表示二维空间中的点。类中包含两个成员变量,分别表示x
和y
坐标,以及相应的构造函数、访问器(getter)和修改器(setter)函数。
class Point { private:double x;double y; public:Point(double _x = 0, double _y = 0) : x(_x), y(_y) {}double getX() const { return x; }double getY() const { return y; }void setX(double newX) { x = newX; }void setY(double newY) { y = newY; } };
- 首先,定义一个
- 使用示例
- 在
main
函数或者其他函数中,可以创建Point
类的对象并操作它。
int main() {Point p(3.0, 4.0);std::cout << "点的坐标: (" << p.getX() << ", " << p.getY() << ")" << std::endl;return 0; }
- 在
- 类的定义
- 操作符重载
- 加法操作符重载
- 为
Point
类重载+
操作符,使得两个Point
对象可以相加,结果是一个新的Point
对象,其坐标分别为两个原始点对应坐标之和。
Point operator+(const Point& p1, const Point& p2) {return Point(p1.getX() + p2.getX(), p1.getY() + p2.getY()); }
- 使用示例:
int main() {Point p1(1.0, 2.0);Point p2(3.0, 4.0);Point sum = p1 + p2;std::cout << "相加后的点坐标: (" << sum.getX() << ", " << sum.getY() << ")" << std::endl;return 0; }
- 为
- 输出流操作符重载
- 重载
<<
操作符,以便能够直接将Point
对象输出到标准输出流。
std::ostream& operator<<(std::ostream& os, const Point& p) {os << "(" << p.getX() << ", " << p.getY() << ")";return os; }
- 使用示例:
int main() {Point p(5.0, 6.0);std::cout << "点: " << p << std::endl;return 0; }
- 重载
- 加法操作符重载
- 有理数类设计
- 类定义
- 有理数由分子和分母组成,在类中需要考虑约分、符号处理等问题。
class Rational { private:int numerator;int denominator;void simplify() {int gcd = std::gcd(numerator, denominator);numerator /= gcd;denominator /= gcd;if (denominator < 0) {numerator = -numerator;denominator = -denominator;}} public:Rational(int num = 0, int den = 1) : numerator(num), denominator(den) {simplify();}int getNumerator() const { return numerator; }int getDenominator() const { return denominator; }Rational operator+(const Rational& r) const {int newNum = numerator * r.denominator + r.numerator * denominator;int newDen = denominator * r.denominator;return Rational(newNum, newDen);} };
- 使用示例
- 创建有理数对象并进行加法运算。
int main() {Rational r1(1, 2);Rational r2(1, 3);Rational sum = r1 + r2;std::cout << "两有理数相加结果: " << sum.getNumerator() << "/" << sum.getDenominator() << std::endl;return 0; }
- 类定义
- token扫描器类设计
- 类定义与功能概述
- token扫描器用于将输入的字符串分割成一个个有意义的token。类中包含输入字符串、当前扫描位置等成员变量,以及扫描下一个token、判断是否结束等成员函数。
class TokenScanner { private:std::string input;size_t pos; public:TokenScanner(const std::string& str) : input(str), pos(0) {}std::string nextToken() {while (pos < input.size() && std::isspace(input[pos])) {pos++;}if (pos >= input.size()) {return "";}size_t start = pos;while (pos < input.size() &&!std::isspace(input[pos])) {pos++;}return input.substr(start, pos - start);}bool hasMoreTokens() {return pos < input.size();} };
- 使用示例
- 输入一个字符串,通过扫描器获取其中的token。
int main() {std::string test = "hello world";TokenScanner scanner(test);while (scanner.hasMoreTokens()) {std::string token = scanner.nextToken();std::cout << "Token: " << token << std::endl;}return 0; }
- 类定义与功能概述
- 将程序封装成类
- 整体思路
- 以一个简单的数学计算程序为例,把计算逻辑封装到一个类中。假设要封装一个计算圆面积的程序,类中包含半径成员变量、计算面积的函数等。
class CircleAreaCalculator { private:double radius; public:CircleAreaCalculator(double r) : radius(r) {}double calculateArea() const {return 3.14 * radius * radius;} };
- 使用示例
- 创建类的对象,调用计算函数。
int main() {CircleAreaCalculator calculator(5.0);double area = calculator.calculateArea();std::cout << "圆的面积: " << area << std::endl;return 0; }
- 整体思路
通过以上设计,可以将不同的功能需求通过类的形式进行良好的组织,提高代码的模块化、可复用性和可读性。