Skip to content

Commit cd8f461

Browse files
committed
C++
1 parent 87a93d2 commit cd8f461

File tree

1 file changed

+251
-23
lines changed

1 file changed

+251
-23
lines changed

src/develop/CPP/3_Class&object.md

Lines changed: 251 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -671,6 +671,149 @@ int main()
671671

672672
添加静态成员可以增强 `Date` 类的功能性和实用性,特别是当需要跟踪或共享与日期相关的通用信息时。
673673

674+
675+
676+
#### 举例
677+
678+
**静态函数实现**
679+
680+
```cpp
681+
class Point {
682+
private:
683+
double x, y;
684+
685+
public:
686+
Point(double x, double y) : x(x), y(y) {}
687+
688+
static double distance(const Point& point1, const Point& point2) {
689+
return sqrt(pow(point1.x - point2.x, 2) + pow(point1.y - point2.y, 2));
690+
}
691+
};
692+
693+
```
694+
695+
调用方式:
696+
697+
```cpp
698+
Point p1(1.0, 2.0);
699+
Point p2(4.0, 6.0);
700+
double dist = Point::distance(p1, p2);
701+
702+
```
703+
704+
**非静态函数实现**
705+
706+
```cpp
707+
class Point {
708+
private:
709+
double x, y;
710+
711+
public:
712+
Point(double x, double y) : x(x), y(y) {}
713+
714+
double distance(const Point& other) const {
715+
return sqrt(pow(x - other.x, 2) + pow(y - other.y, 2));
716+
}
717+
};
718+
719+
```
720+
721+
调用方式:
722+
723+
```cpp
724+
Point p1(1.0, 2.0);
725+
Point p2(4.0, 6.0);
726+
double dist = p1.distance(p2);
727+
```
728+
729+
730+
731+
**1. 非静态函数需要依赖对象实例**
732+
733+
- **当前实现(`static`)**:
734+
- `distance` 是一个静态成员函数,与具体的 `Point` 对象无关。
735+
- 调用时可以直接通过类名调用,例如:`Point::distance(point1, point2)`。
736+
- 静态函数不能访问类的非静态成员变量(如 `x` 和 `y`),因为它不依赖于任何对象实例。
737+
738+
- **如果去掉 `static`**:
739+
- `distance` 将变成一个非静态成员函数,必须通过某个 `Point` 对象调用。
740+
- 例如:`point1.distance(point2)`,此时 `distance` 函数的第一个参数隐式绑定到调用它的对象 `point1`。
741+
742+
**2. 函数签名的变化**
743+
744+
- **当前签名(静态函数)**:
745+
```cpp
746+
static double distance(const Point& point1, const Point& point2);
747+
748+
```
749+
- 需要显式传入两个 `Point` 对象作为参数。
750+
751+
- **去掉 `static` 后的签名**
752+
753+
```cpp
754+
double distance(const Point& other) const;
755+
756+
```
757+
- 只需要传入一个 `Point` 对象作为参数,另一个 `Point` 对象是调用该函数的对象(`this` 指针)。
758+
759+
**3. 使用方式的变化**
760+
761+
**当前(静态函数)**
762+
763+
调用方式:
764+
765+
```cpp
766+
Point point1(1.0, 2.0);
767+
Point point2(4.0, 6.0);
768+
double dist = Point::distance(point1, point2); // 通过类名调用
769+
770+
```
771+
772+
**去掉 `static` 后(非静态函数)**
773+
774+
调用方式:
775+
776+
```cpp
777+
Point point1(1.0, 2.0);
778+
Point point2(4.0, 6.0);
779+
double dist = point1.distance(point2); // 通过对象调用
780+
781+
```
782+
783+
**4. 设计上的影响**
784+
785+
- **静态函数的优点**:
786+
- 逻辑上更清晰:`distance` 函数的功能是计算两点之间的距离,与某个具体的 `Point` 对象无关,因此设计为静态函数更符合直觉。
787+
- 更灵活:可以直接通过类名调用,而不需要依赖某个对象实例。
788+
789+
- **非静态函数的优点**:
790+
- 如果 `distance` 函数的逻辑需要频繁使用调用对象的成员变量(如 `x` 和 `y`),设计为非静态函数可能更方便。
791+
- 例如,调用 `point1.distance(point2)` 时,`point1` 的坐标可以直接通过 `this` 指针访问。
792+
793+
**5. 性能上的影响**
794+
795+
- **静态函数**:
796+
- 不需要传递隐式的 `this` 指针,调用开销略低。
797+
- 更适合与类的实例无关的功能。
798+
799+
- **非静态函数**:
800+
- 需要传递隐式的 `this` 指针,调用开销略高。
801+
- 适合需要访问调用对象的成员变量的功能。
802+
803+
**6. 结论**
804+
805+
- **保留 `static`**:
806+
- 如果 `distance` 函数的逻辑与具体的 `Point` 对象无关(如当前实现),设计为静态函数更合理。
807+
- 适合计算两点之间的距离这种独立于对象的功能。
808+
809+
- **去掉 `static`**:
810+
- 如果希望通过调用对象直接计算与另一个点的距离,设计为非静态函数更方便。
811+
- 适合需要频繁访问调用对象的成员变量的功能。
812+
813+
在上面的场景中,`distance` 函数的逻辑与具体的 `Point` 对象无关,因此保留 `static` 是更好的选择。
814+
815+
816+
674817
### 6.3 `static const` 成员
675818
676819
`static const` 成员是C++类中的特殊成员,它们结合了静态成员的共享性和常量成员的不可修改性。这种成员在所有对象间共享,并且在程序执行期间其值不会改变。
@@ -852,7 +995,7 @@ int main() {
852995
853996
## 8 作业
854997
855-
按需求设计一个圆类输入圆的半径和圆柱的高,依次输出圆周长、圆面积、圆球表面积、圆柱体积(以空格分隔,π取 3.14)。
998+
设计一个圆类,输入圆的半径和圆柱的高,依次输出圆周长、圆面积、圆球表面积、圆柱体积(以空格分隔,π取 3.14)。
856999
```cpp
8571000
#include <iostream>
8581001
@@ -866,28 +1009,28 @@ private:
8661009
float circumference; //圆的周长
8671010
float volume; //圆的体积
8681011
float surface; //圆的表面积
869-
static const float PI = 3.14; //圆周率
1012+
static const float PI; // 静态常量 圆周率
8701013
8711014
public:
8721015
circle(float r = 0, float h = 0); //构造函数
8731016
~circle();
874-
1017+
8751018
// 计算圆周长
8761019
float calculateCircumference();
877-
1020+
8781021
// 计算圆面积
8791022
float calculateArea();
880-
1023+
8811024
// 计算圆球表面积
8821025
float calculateSphereArea();
883-
1026+
8841027
// 计算圆柱体积
8851028
float calculateCylinderVolume();
886-
887-
// 设置半径和高
888-
void setValues(float r, float h);
8891029
};
8901030
1031+
// 在类外初始化静态常量
1032+
const float circle::PI = 3.14;
1033+
8911034
circle::circle(float r, float h)
8921035
{
8931036
radius = r;
@@ -922,31 +1065,116 @@ float circle::calculateCylinderVolume()
9221065
return volume;
9231066
}
9241067
925-
void circle::setValues(float r, float h)
926-
{
927-
radius = r;
928-
high = h;
929-
}
930-
9311068
int main()
9321069
{
9331070
float radius, high;
934-
1071+
9351072
// 输入半径和高
9361073
std::cin >> radius >> high;
937-
1074+
9381075
// 创建circle对象并设置值
9391076
circle c(radius, high);
940-
1077+
9411078
// 计算并输出结果,以空格分隔
9421079
std::cout << c.calculateCircumference() << " "
943-
<< c.calculateArea() << " "
944-
<< c.calculateSphereArea() << " "
945-
<< c.calculateCylinderVolume() << std::endl;
946-
1080+
<< c.calculateArea() << " "
1081+
<< c.calculateSphereArea() << " "
1082+
<< c.calculateCylinderVolume() << std::endl;
1083+
9471084
return 0;
9481085
}
9491086
9501087
```
9511088

952-
编写C++程序完成以下功能: 1)定义一个 Point 类,其属性包括点的坐标,提供计算两点之间距离的方法;2)定义一个圆形类, a.其属性包括圆心和半径; b.创建两个圆形对象,提示用户输入圆心坐标和半径,判断两个圆是否相交,并输出结果。
1089+
1090+
1091+
1)定义一个 Point 类,其属性包括点的坐标,提供计算两点之间距离的方法;2)定义一个圆形类, a.其属性包括圆心和半径; b.创建两个圆形对象,提示用户输入圆心坐标和半径,判断两个圆是否相交,并输出结果。
1092+
1093+
**Point.h**
1094+
1095+
```cpp
1096+
#pragma once
1097+
class Point
1098+
{
1099+
1100+
private:
1101+
double x;
1102+
double y;
1103+
1104+
public:
1105+
Point(double x, double y) : x(x), y(y)
1106+
{
1107+
}
1108+
1109+
static double distance(const Point& point1, const Point& point2)
1110+
{
1111+
return sqrt(pow(point1.x - point2.x, 2) + pow(point1.y - point2.y, 2));
1112+
}
1113+
};
1114+
1115+
1116+
```
1117+
1118+
**Circle.h**
1119+
1120+
```cpp
1121+
#pragma once
1122+
#include "Point.h"
1123+
class Circle
1124+
{
1125+
private:
1126+
Point center; // 圆心
1127+
double radius; // 半径
1128+
1129+
public:
1130+
// 构造函数
1131+
Circle(const Point& center, double radius) : center(center), radius(radius) {}
1132+
1133+
// 获取圆心
1134+
const Point& getCenter() const { return center; }
1135+
1136+
// 获取半径
1137+
double getRadius() const { return radius; }
1138+
1139+
// 判断两个圆是否相交
1140+
static bool isIntersecting(const Circle& circle1, const Circle& circle2) {
1141+
double distance = Point::distance(circle1.getCenter(), circle2.getCenter());
1142+
return distance <= (circle1.getRadius() + circle2.getRadius());
1143+
}
1144+
};
1145+
1146+
```
1147+
1148+
**GeometryUtils.cpp**
1149+
1150+
```cpp
1151+
#include <iostream>
1152+
#include "Circle.h"
1153+
1154+
int main() {
1155+
// 提示用户输入第一个圆的圆心坐标和半径
1156+
double x1, y1, r1;
1157+
std::cout << "Enter the center (x, y) and radius of the first circle: ";
1158+
std::cin >> x1 >> y1 >> r1;
1159+
1160+
// 提示用户输入第二个圆的圆心坐标和半径
1161+
double x2, y2, r2;
1162+
std::cout << "Enter the center (x, y) and radius of the second circle: ";
1163+
std::cin >> x2 >> y2 >> r2;
1164+
1165+
// 创建两个圆形对象
1166+
Circle circle1(Point(x1, y1), r1);
1167+
Circle circle2(Point(x2, y2), r2);
1168+
1169+
// 判断两个圆是否相交
1170+
if (Circle::isIntersecting(circle1, circle2)) {
1171+
std::cout << "The two circles intersect." << std::endl;
1172+
}
1173+
else {
1174+
std::cout << "The two circles do not intersect." << std::endl;
1175+
}
1176+
1177+
return 0;
1178+
}
1179+
```
1180+

0 commit comments

Comments
 (0)