c++ 类与对象 拆分
题目:设计一个圆形类和一个点类,判断圆与点的关系
写法1:将其写在一个mian.cpp文件中
#include <iostream>
using namespace std;
//定义一个点类
class Point {
private:
int p_X;
int p_Y;
public:
void setX (int x) noexcept{
p_X = x;
}
int getX() noexcept{
return p_X;
}
void setY(int y) noexcept{
p_Y = y;
}
int getY() noexcept{
return p_Y;
}
};
//定义一个圆类
class Circle {
private:
int c_R;
Point center;
public:
void setR(int r) noexcept {
c_R = r;
}
int getR() noexcept {
return c_R;
}
void setCenter(Point p) {
center.setX(p.getX());
center.setY(p.getY());
}
Point getCenter() noexcept {
return center;
}
};
void pointInCircle(Circle c, Point p) {
//计算点到圆心的距离
int const c_x = c.getCenter().getX();
int const c_y = c.getCenter().getY();
int const distance = (c_x - p.getX()) * (c_x - p.getX()) + (c_y - p.getY()) * (c_y - p.getY());
//获取半径
int const c_r = c.getR();
//判断圆与点的关系
if (distance == c_r * c_r) {
cout << "点在圆上" << endl;
}
else if (distance > c_r * c_r) {
cout << "点在圆外" << endl;
}
else {
cout << "点在圆内" << endl;
}
};
int main() {
cout << " hello world" << endl;
//设置点
Point p1;
p1.setX(10);
p1.setY(10);
//定义圆心
Point p2;
p2.setX(10);
p2.setY(0);
//设置圆的半径和圆心
Circle c1;
c1.setR(10);
c1.setCenter(p2);
cout << c1.getCenter().getX() << "," << c1.getCenter().getY() << endl;
pointInCircle(c1, p1);
}
在设计类的时候,一般把类中的成员变量设置为private权限,再加上权限为public的权限的成员函数(一般为setValue和getValue),就可以实现对成员读写控制,更好的实现封装。
优缺点:这样写比较方便阅读代码,但是对于大型程序设计中,显然不可能把所有的类都写在一个cpp文件中,在平时程序设计中,** 一般是通过每个类拆分成一个头文件和一个实现类,头文件中实现函数声明,实现类中实现函数功能功能。 **
于是我们对上面的案例进行拆分,具体来说:
//把一个实现类可以拆成一个头文件和一个具体实现,在头文件中只保留成员变量和成员函数声明(不包括具体实现)
//而在具体实现中包括只包括函数具体实现(需要标明作用域)
代码结构图如下:
点类
头文件: point.h
实现对poin类中的所有成员变量和成员函数的声明:
#pragma once //防止头文件被重复包含
#include <iostream>
using namespace std;
class Point {
private:
int p_X;
int p_Y;
public:
void setX(int x);
int getX();
void setY(int y);
int getY();
};
对应的point类的具体实现:需要包含point.h,对其中包含的函数声明进行具体实现,如下:
#include <iostream>
using namespace std;
#include "point.h"
void Point::setX(int x) {
p_X = x;
}
int Point::getX() {
return p_X;
}
void Point::setY(int y) {
p_Y = y;
}
int Point::getY() {
return p_Y;
}
圆类
头文件:
#pragma once
#include <iostream>
using namespace std;
//定义一个圆类
class Circle {
private:
int c_R;
Point center;
public:
void setR(int r);
int getR();
void setCenter(Point p);
Point getCenter();
};
具体实现:
#include <iostream>
#include "point.h" //在circle类中,使用了point类中
#include "circle.h"
using namespace std;
//设置圆的半径
void Circle::setR(int r) {
c_R = r;
}
//获取圆的半径
int Circle::getR() {
return c_R;
}
//设置圆心坐标
void Circle::setCenter(Point p) {
center.setX(p.getX());
center.setY(p.getY());
}
//获取圆心坐标
Point Circle::getCenter() {
return center;
}
主函数
#include <iostream>
#include "point.h"
#include "circle.h"
using namespace std;
//判断点与圆的关系
void pointInCircle(Circle c, Point p) {
//计算点到圆心的距离
int const c_x = c.getCenter().getX();
int const c_y = c.getCenter().getY();
int const distance = (c_x - p.getX()) * (c_x - p.getX()) + (c_y - p.getY()) * (c_y - p.getY());
//获取半径
int const c_r = c.getR();
//判断圆与点的关系
if (distance == c_r * c_r) {
cout << "点在圆上" << endl;
}
else if (distance > c_r * c_r) {
cout << "点在圆外" << endl;
}
else {
cout << "点在圆内" << endl;
}
};
int main() {
//设置点
Point p1;
p1.setX(10);
p1.setY(10);
//定义圆心
Point p2;
p2.setX(10);
p2.setY(0);
//设置圆的半径和圆心
Circle c1;
c1.setR(10);
c1.setCenter(p2);
pointInCircle(c1, p1);
}
构造函数
有三种构造函数形式:
无参构造:编译器默认提供
有参构造:支持函数重载
拷贝构造:
Person p1; //无参构造
Person p2(10);//有参构造
Person p3(p2);//拷贝构造
匿名对象
Person(10); //匿名对象:当前执行结束之后,系统会立即回收掉匿名对象
拷贝构造函数的调用时机:
1、使用一个已经创建完毕的对象来初始化一个新对象
2、值传递的方式给函数参数传值
3、值方式返回局部对象
构造函数调用规则:
默认情况下,c++编译器下至少会给一个类提供3个函数
1、默认构造函数(无参,函数体为空)
2、默认析构函数(无参,函数体为空)
3、默认拷贝构造函数,对属性进行值拷贝
调用规则如下:
- 如果用户定义了有参构造函数,c++不在提供默认的无参构造,但是会提供默认拷贝构造。
- 如果用户定义拷贝构造函数,c++不会再提供其他构造函数。
深拷贝和浅拷贝
浅拷贝:简单的赋值拷贝操作。
深拷贝:在堆区重新申请空间,进行拷贝操作。
静态成员
静态成员就是在成员变量和成员函数前加上关键字static,称为静态成员。
静态成员分为:
-
静态成员变量
所有对象共享同一份数据
在编译阶段分配内存
类内声明,类外初始化 -
静态成员函数
所有对象共享同一个函数
静态成员函数只能访问静态成员变量(不能访问非静态成员变量,因为无法区分是哪个对象的)