一、基本概念
对象:对象是一个实体,我们看到的所有实体都可以看做一个对象。
类:类是用来对实体(对象)进行描述的,类中定义了对象的属性、功能等内容。类是一种自定义类型。
方法:方法是实现类功能的一个具体实现,该类有什么样的功能都要通过调用方法来实现。
定义类的格式:
class 类名{
//类体
//成员变量
//成员函数
}
例如我们定义一个Person类,类中包含姓名,年龄等成员属性;以及“讲话”这个成员函数。
class Person{
public:
string name;
int age;
void speak(){
cout<<"讲话"<<endl;
}
}
定义类成员,使用成员属性,成员函数:
Person p;
p.m_name = "张三";
p.m_age = 18;
p.speak();
二、访问权限
概念:控制哪些成员可以在类外直接被访问,哪些只能通过方法进行访问。struct默认访问权限是 public,class 默认访问权限是 private。
访问限定符:
公共权限 public:类内可以访问,类外也可以访问。
保护权限 protected:类内可以访问,类外不可以访问。子类可以访问父类中的保护内容。
私有权限 private:类内可以访问,类外不可以访问。子类不可以访问父类的私有内容。
三、示例
如果你是初学者,现在可能有点懵逼,什么是访问权限?各个访问权限的区别在哪儿?子类和父类是啥意思?成员函数怎么定义怎么使用?别急,先不管访问权限,先看个简单的例子:
示例一:设计一个学生类,成员属性有姓名和学号,成员函数包含以下功能:可以给姓名和学号赋值,可以显示学生的姓名和学号信息。
#include<iostream>
using namespace std;
class student {
public:
//成员属性
string m_name;
string m_id;
//成员函数
//显示姓名和学号
void showStudent() {
cout << "姓名:" << m_name << "学号:" << m_id << endl;
}
//给姓名赋值
void setName(string name) {
m_name = name;
}
//给学号赋值
void setID(string id) {
m_id = id;
}
};
int main() {
student s;
string name, id;
cout << "请输入学生姓名:";
cin >> name;
s.setName(name);
cout << "请输入学生学号:";
cin >> id;
s.setID(id);
s.showStudent();
return 0;
}
上面这个示例看明白之后,你已经可以设计一个简单的类了,现在再看一个示例,这里面我们理解一下公共权限和私有权限的区别和用途,保护权限主要用在继承体系中,这里先不作展示。
示例二:设计一个圆形类和一个点类,使其可以通过输入点的(x,y)坐标和圆的半径 r 判断点和圆的位置关系(在圆内,在圆上,在圆外)。本例中 圆心的坐标 以及 输入的点 的坐标都是已经设置好的,圆心(10,0),当然你也可以优化代码让这些信息通过用户输入确定。
#include<iostream>
#include<string>
using namespace std;
//点类
class point {
public:
void setX(int x) { //设置x坐标
m_x = x;
}
void setY(int y) { //设置y坐标
m_y = y;
}
int getX() { //获取x坐标
return m_x;
}
int getY() { //获取y坐标
return m_y;
}
private:
int m_x;
int m_y;
};
//圆类
class circle {
public:
void setR(int r) { //设置半径r
m_r = r;
}
int getR() { //获取半径r
return m_r;
}
void setCenter(point center) { //设置圆心
m_center = center;
}
point getCenter() { //获取圆心
return m_center;
}
private:
int m_r; //半径
point m_center; //圆心
};
//判断点和圆的关系函数
void isInCircle(circle& c, point& p) {
//计算两点距离的平方
int distance = (c.getCenter().getX() - p.getX()) * (c.getCenter().getX() - p.getX()) +
(c.getCenter().getY() - p.getY()) * (c.getCenter().getY() - p.getY());
//计算半径的平方
int r_distance = c.getR() * c.getR();
//判断关系
if (distance == r_distance) {
cout << "点在圆上" << endl;
}
else if(distance > r_distance){
cout << "点在圆外" << endl;
}
else {
cout << "点在圆内" << endl;
}
}
int main() {
//创建圆
circle c;
c.setR(10); //设置半径
point center; //定义圆心
center.setX(10); //圆心点x坐标
center.setY(0); //圆心点y坐标
c.setCenter(center);//圆心 (10,0)
//创建点
point p;
p.setX(20);
p.setY(1); //点(10,10)
//判断关系
isInCircle(c, p);
return 0;
}
这里面我们发现,私有权限我们都在类内设置了一个接口(成员函数)来对他们进行更改。比如 point 类中的私有属性 m_x 和 m_y ,我们无法在类外直接访问,比如你在类外创建一个 point类的成员 p ,就不能通过 p.m_x=10 来更改私有属性 m_x 的值,只能通过类内的接口 set(int x) 来更改。而公共权限可以直接在类外修改。
这就是私有权限和公共权限的区别。
四、将不同的类保存在多个文件中
我们以上述例二为例,我们总共创建了两个类,point类和circle类,仅是这两个简单的类,我们的代码就已经近80行,如果我们的类再多一些,再复杂一些,代码会显得冗杂。
所以我们有必要知道如何将不同的类保存在多个文件中,使我们的主函数代码文件更简洁。
1.在“头文件”中创建名为“circle.h”和“point.h”的两个头文件
将circle类和point类的成员变量和成员函数分别粘贴在对应的头文件中。文件最上方加一行“#pragma.once”,该代码的作用是防止头文件重复包含。
①circle.h
#pragma once
#include "point.h"
#include<iostream>
using namespace std;
//圆类
class circle {
public:
void setR(int r);
int getR();
void setCenter(point center);
point getCenter();
private:
int m_R; //半径
point m_center; //圆心
};
②point.h
#pragma once //防止头文件重复包含
#include<iostream>
using namespace std;
//点类
//只需要作成员变量的声明就可以了,不需要实现
class point {
public:
void setX(int x);
void setY(int y);
int getX();
int getY();
private:
int m_X;
int m_Y;
};
注意:头文件只需要成员变量和成员函数的声明,不需要实现内容。
2.在“源文件”中创建两个名为“circle.cpp”和“point.cpp”的文件
①circle.cpp
#include "circle.h"
//在circle::作用域下,只保留实现
void circle::setR(int r) { //设置半径r
m_R = r;
}
int circle::getR() { //获取半径r
return m_R;
}
void circle::setCenter(point center) { //设置圆心
m_center = center;
}
point circle::getCenter() { //获取圆心
return m_center;
}
②point.cpp
#include "point.h"
//点类
//前面加“point::”是为了告诉程序各个变量是在point作用域下的
void point::setX(int x) { //设置x坐标
m_X = x;
}
void point::setY(int y) { //设置y坐标
m_Y = y;
}
int point::getX() { //获取x坐标
return m_X;
}
int point::getY() { //获取y坐标
return m_Y;
}
注意:1.在代码开头引用自己的头文件。
2.在这里面做成员函数实现。在成员函数前面加上它的作用域,比如是circle类的成员函数,就加上“circle::”,表示这是circle类的成员函数。
3.主函数文件中引用头文件“circle.h”和“point.h”
#include<iostream>
#include<string>
#include "circle.h"
#include "point.h"
using namespace std;
void isInCircle(circle& c, point& p) {
//计算两点距离的平方
int distance = (c.getCenter().getX() - p.getX()) * (c.getCenter().getX() - p.getX()) +
(c.getCenter().getY() - p.getY()) * (c.getCenter().getY() - p.getY());
//计算半径的平方
int r_distance = c.getR() * c.getR();
//判断关系
if (distance == r_distance) {
cout << "点在圆上" << endl;
}
else if(distance > r_distance){
cout << "点在圆外" << endl;
}
else {
cout << "点在圆内" << endl;
}
}
int main() {
//创建圆
circle c;
c.setR(10); //设置半径
point center; //定义圆心
center.setX(10); //圆心点x坐标
center.setY(0); //圆心点y坐标
c.setCenter(center);//圆心 (10,0)
//创建点
point p;
p.setX(20);
p.setY(1); //点(10,10)
//判断关系
isInCircle(c, p);
return 0;
}
引用头文件之后,把circle类和point类相关的那部分代码删掉就可以,其他部分不用动。这样我们的代码就会简洁很多,在未来编程过程中这种模式也是会一直使用到的。
五、类和对象其他基础知识可以参考我的另两篇博客
C/C++笔记总结——构造函数,析构函数,深拷贝与浅拷贝(含解决浅拷贝带来的问题)_给你糖ya的博客-CSDN博客
C/C++笔记总结——类对象作为类成员,静态成员,对象模型和this指针(返回值类型和引用类型的区别)_给你糖ya的博客-CSDN博客