C++类和对象(一):封装


0 类和对象

C++面向对象的三大特性:封装、继承、多态
C++中万物皆对象,对象包含属性(成员变量/成员属性)和行为(成员函数/成员方法)。


1 封装的意义

封装的意义
(1)将属性和行为作为一个整体,表征现实的事物;
(2)对属性和行为进行权限控制

访问权限包括3种:
public公共权限——成员在类中和类外均可访问
protected保护权限——成员在类中可访问,类外不可访问;子类可访问父类的保护成员。
private私有权限——成员在类中可访问,类外不可访问;子类不可访问父类的私有成员。

注1:protectedprivate的主要区别在于继承方面,即子类是否可以访问父类的相关成员:protected子类可访问父类的保护成员;private子类不可访问父类的私有成员。
注2:类中的函数内部,仍属于类中,可访问任意权限的类成员。
注3:类class的默认权限为私有private
注4:类的作用域属于类内,如类型::成员,可访问类中的私有成员私有构造函数

类的定义

class 类名{
    
    
访问权限:
	属性/行为
};

实例化:通过类创建一个具体的对象。

示例

#include <iostream>
using namespace std;

const double PI = 3.14;

class Circle {
    
    
private:	//访问权限:私有权限(类中可访问,类外不可访问)
	/* 类的属性:成员变量 */
	int radius;
	
public:		//访问权限:公共权限(类中和类外均可访问)
	/* 类的行为:成员函数 */
	void setRadius(int r){
    
    
		radius = r;
	}

	double calculateArea() {
    
    
		return PI * radius * radius;
	}
};

int main() {
    
    
	//实例化对象
	Circle c;
	c.setRadius(1);

	double area = c.calculateArea();
	cout << area << endl;
	
	return 0;
}

2 结构体struct和类class区别

C++中,结构体struct类class均可表征一个类,唯一区别在于默认的访问权限不同
(1)结构体struct的默认权限为公共public
(2)类class的默认权限为私有private

示例

/* 
	结构体的默认权限是公共public
	类的默认权限是私有private
*/
class Class {
    
    
	int field;	//默认是私有,类外不可访问
};

struct Struct {
    
    
	int field;	//默认是公有,结构体外科访问
};

int main() {
    
    
	/* 结构体的默认权限是公共public */
	Struct s;
	s.field = 1;	//可访问

	/* 类的默认权限是私有private */
	Class c;
	//c.field = 2;	//报错:Class::field不可访问

	return 0;
}

3 成员属性设置为私有

将所有成员属性设置为私有的优点
(1)可使用getter/setter函数控制读写权限,避免成员属性被外部直接访问或修改;
(2)对于写权限,可使用逻辑判断语句校验写入数据的有效性

示例

#include <iostream>
using namespace std;
#include <string>

class Person {
    
    
private:
	string _name;	//设置读写权限
	int _age;		//设置读写权限

public:
	/* 使用 getter/setter函数 控制读写权限 */
	void setName(string name) {
    
    
		_name = name;
	}
	
	string getName() {
    
    
		return _name;
	}

	void setAge(int age) {
    
    
		/* 校验写入数据的有效性 */
		if (age < 0 || age > 120) {
    
    
			cout << "输入的年龄有误" << endl;
			_age = 0;
			return;
		}
		_age = age;
	}

	int getAge() {
    
    
		return _age;
	}
};

int main() {
    
    
	Person p;

	p.setName("Tom");
	cout << "姓名:" << p.getName() << endl;

	//p.setAge(200);	//数据不在有效范围
	p.setAge(20);
	cout << "年龄:" << p.getAge() << endl;

	return 0;
}

4 封装特性的练习案例:点和圆的位置关系

创建圆类(Circle)和点类(Point),根据点与圆心的距离判断点和圆的位置关系。
重点
(1)不同类的分文件编写:头文件和源文件中成员函数的写法、头文件包含;

头文件成员属性和成员函数的声明
源文件包含头文件成员函数的定义,使用作用域限定符类名::成员函数名指定成员函数所属的类作用域。

注:头文件中使用宏#pragma once#ifndef,可防止头文件被重复包含

(2)一个类的成员属性是另一个类的对象(圆类的圆心是点类的对象);
(3)分别使用全局函数和成员函数【形参个数的不同】,判断点和圆的位置关系;
(4)函数形参使用引用替代变量,可避免数据拷贝,减少内存占用。

示例
点类头文件point.h

/* 头文件:成员属性和成员函数的声明 */
#pragma once	//防止头文件被重复包含
#include <iostream>
using namespace std;

class Point {
    
    
private:
	double X;	//横坐标
	double Y;	//纵坐标

public:
	/* 横坐标的设置与获取 */
	void setX(double x);
	double getX();

	/* 纵坐标的设置与获取 */
	void setY(double y);
	double getY();

	/* 两点的距离 */
	//函数形参使用引用替代变量,可避免数据拷贝,减少内存占用
	double getDistance(Point &p);
};

点类源文件point.cpp

/* 源文件:成员函数的定义 */
//使用 作用域限定符 `类名::成员函数名` 指定成员函数所属的类作用域

#include "point.h"
#include <cmath>	//数学方法

void Point::setX(double x) {
    
    
	X = x;
}

double Point::getX() {
    
    
	return X;
}

void Point::setY(double y) {
    
    
	Y = y;
}

double Point::getY() {
    
    
	return Y;
}

/* 成员函数:计算两点的距离 */
//函数形参使用引用替代变量,可避免数据拷贝,减少内存占用
double Point::getDistance(Point &p) {
    
    
	return sqrt(pow(X - p.getX(), 2) + pow(Y - p.getY(), 2));
}

圆类头文件circle.h

/* 头文件:成员属性和成员函数的声明 */
#pragma once	//防止头文件被重复包含
#include <iostream>
using namespace std;

#include "point.h"

class Circle {
    
    
private:
	double radius;		//半径
	Point center;	//圆心

public:
	/* 半径的设置与获取 */
	void setRadius(double r);
	double getRadius();

	/* 圆心的设置与获取 */
	void setCenter(Point p);
	Point getCenter();
};


圆类源文件circle.cpp

/* 源文件:成员函数的定义 */
//使用 作用域限定符 `类名::成员函数名` 指定成员函数所属的类作用域

#include "circle.h"

/* 半径的设置与获取 */
void Circle::setRadius(double r) {
    
    
	radius = r;
};

double Circle::getRadius() {
    
    
	return radius;
};

/* 圆心的设置与获取 */
void Circle::setCenter(Point p) {
    
    
	center = p;
};

Point Circle::getCenter() {
    
    
	return center;
};

测试源文件main.cpp

#include <iostream>
using namespace std;

#include "point.h"
#include "circle.h"

/* 全局函数:计算两点的距离 */
//函数形参使用引用替代变量,可避免数据拷贝,减少内存占用
double g_getDistance(Circle &c, Point &p) {
    
    
	return sqrt(pow(c.getCenter().getX() - p.getX(), 2) 
		      + pow(c.getCenter().getY() - p.getY(), 2));
}

/* 判断点与圆的位置关系 */
void isInCircle(double distance, double radius) {
    
    
	if (distance < radius) {
    
    
		cout << "点在圆内" << endl;
	}
	else if (distance == radius) {
    
    
		cout << "点在圆上" << endl;
	}
	else if (distance > radius) {
    
    
		cout << "点在圆外" << endl;
	}
}

int main() {
    
    
	/* 实例化圆类对象 */
	Circle c;
	c.setRadius(1);	//设置半径
	double r = c.getRadius();

	//设置圆心
	Point center;
	center.setX(0);
	center.setY(0);
	c.setCenter(center);

	/* 实例化点类对象 */
	Point p;
	p.setX(0);
	p.setY(0.99);	//点在圆内

	/* 使用成员函数判断两点距离及位置关系 */
	double d1 = p.getDistance(center);
	cout << "点和圆心的距离:" << d1 << endl;	//0.99
	isInCircle(d1, r);				//点在圆内

	/* 使用全局函数判断两点距离及位置关系 */
	double d2 = g_getDistance(c, p);
	cout << "点和圆心的距离:" << d2 << endl;	//0.99
	isInCircle(d2, r);				//点在圆内

	return 0;
}

猜你喜欢

转载自blog.csdn.net/newson92/article/details/113007286