C++类和对象(一)

前言:c++作为一款面向对象语言,其面向过程是C/C++之间最大的区别之一。C++类的类和对象思想最开始是起源于C语言的结构体。在C++中对C语言进行了拓展,同时衍生了一种全新的语言特型——类。

一、什么是面向对象?

在解释这个问题之前,我们可以设想一个场景,我们在点外卖的时候,会经过以下的过程:Ⅰ用户在平台下单,商户接单,外卖员进行接单,然后商家开始制作菜品,外卖员取餐后开始送餐,最后将餐送到你的手中。这便一套流程走下来,便是面向过程的思想。Ⅱ在上面的过程中,一共涉及到了三个对象,用户、商家、外卖小哥。其中用户要做的事情就是下单,然后就是等待接收外卖商家要做的是接单,并且准备菜品外卖小哥需要做的事情就是接单,并且配送菜品,这样,三个人各司其职,将外卖送到用它用户手中。这便是面向过程思想。

我们来对比一下这两种思想

1)面向过程:将一件事情拆分成多个步骤,按照步骤一件一件做好;

2)面向对象:将一件事情拆开,将不同的行为分给不同的对象,每个对象来分别完成自己的工作;

二、类的引入

类一开始起源于C语言中的结构体,在C语言中结构体中只能定义结构变量,不能定义函数,而C++对其进行了拓展,C++中的结构体支持定义函数,在C++中使用了另一个关键字class来标识类,这也是C++刚推出时的最大的特性,首次引入了类的概念。所以,最早的C++也叫做C with classes。

1.C语言结构体

在C语言中,假设我们要定义一个日期类型(年,月,日),我们自然而然会想到一下代码:

#include<stdio.h>
struct Date {
	int year;
	int month;
	int day;
};
int main()
{
	struct Date X;
	X.year = 2024;
	X.month = 1;
	X.day = 27;
	printf("%d-%d-%d\n",X.year,X.month,X.day);
	return 0;
}

运行结果如下:

2.C++结构体

在C++中,对结构体进行了拓展,我们可以这样写:

#include<iostream>
using namespace std;
struct Date {
	int year;
	int month;
	int day;
	void print()
	{
		cout << year << "-" << month << "-" << day << endl;
	}
};
int main()
{
	struct Date X;
	X.year = 2024;
	X.month = 1;
	X.day = 27;
	X.print();
	return 0;
}

运行结果如下:

3.C++类

使用类的写法,我们又可以这样写:

class Date
{
private:
	int _year;
	int _month;
	int _day;
public:
	void Init(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	void print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;

	}
};
int main()
{
	Date x;
	x.Init(2024, 1, 27);
	x.print();
	return 0;
}

运行结果依然相同:

三、类的定义

类的定义由 class关键字+花括号+“分号”组成,类定义的内容在花括号内。

类方法声明定义不分离:

例如上面的例子:

class Date
{
private:
	int _year;
	int _month;
	int _day;
public:
	void Init(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	void print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;

	}
};

这里定义了一个Date类表示日期的类,其中包含 _year、_month、_day三个成员变量,Init、print两个方法。(类中成员由属性,即成员变量和方法组成)。类的主体在花括号之间,最后以分号结尾。

类方法声明和定义分离:

在较大的工程中,可能存在以下情形:在一个类中,有大量方法,每个方法的代码量又比较大,为了更好地维护代码,和C语言中函数的声明定义分离一样,这时我们便需要使用声明和定义分离。

假设现在要将Date类中的方法声明定义分离,我们可以创建两个文件,Date.h用于存放类的定义和方法的声明,Date.cpp用于存放方法的定义。

在Date.h中,我们进行Date的定义以及方法的声明

//this file is "Date.h"
#pragma once 


#include<iostream>
using namespace std;

class Date
{
public:
	Date();
	void Init(int year, int month, int day);
	void print();

private:
	int _year;
	int _month;
	int _day;

};

在Date.cpp中,我们进行成员函数的定义,注意,在进行定义的时候,不能和C语言一样,直接写函数名,而是需要和命名空间一样,使用类名+::+方法名引出。原因在于该方法在类中声明,但是Date.cpp中只包含了Date.h,它并不知道定义的是函数还是方法以及其在哪里声明了,所有要用类名+::告诉Date.cpp定义的是什么,以及其在哪里声明了;

//this file is "Date.cpp"
#include"Date.h"


void Date::Init(int year, int month, int day)
{
	_year = year;
	_month = month;
	_day = day;
}
void Date::print()
{
	cout << _year << "-" << _month << "-" << _day << endl;
}

我们运行一下,发现是对的

四、类的实例化

类的实例化就是创建一个对象,创建我们定义的那一类中的一个对象,就比如我们前面举的那个例子,外卖员是一类人,然后实例化对象就是从外卖员人群中选取一个外卖员个给我们送外卖。其语法是 类名+对象名[+构造参数]。注:构造参数需要定义构造函数才可传参。

Date x;

或者:

Date x(2024,1,27);

五、类的访问限定符

数据封装是面向对象编程的一个重要特点,它防止函数直接访问类类型的内部成员。类成员的访问限制是通过在类主体内部对各个区域标记 public、private、protected 来指定的。关键字 public、private、protected 称为访问修饰符。

一个类可以有多个 public、protected 或 private 标记区域。每个标记区域在下一个标记区域开始之前或者在遇到类主体结束右括号之前都是有效的。成员和类的默认访问修饰符是 private。

public:用public修饰的成员为公有成员,公有成员在程序中类的内部和外部都是可访问的。

private:用private修饰的成员是私有成员,私有成员只在该类的内部可以被访问。在子类中也不能被访问。

protected:用protected修饰的成员是受保护成员,受保护成员和私有成员相似,之能在类的内部使用,但是在子类的内部也可以使用。

访问限定符使用方法:访问限定符的用法是关键字+":",如果未被网文限定符修饰的成员默认为private。

例如:

这里的_year,_month,_day没有被修饰,所以默认为private,直接对其访问结果报错,public修饰Init和print两个成员函数。

1.public修饰成员举例

#include <iostream>

using namespace std;

class Line
{
public:
	double length;
	void Init(double len)
	{
		length = len;
	}
	double getLength()
	{
		return length;
	}
};

int main()
{
	Line line;

	// 设置长度
	line.Init(6.0);
	cout << "Length of line : " << line.getLength() << endl;

	// 不使用成员函数设置长度
	line.length = 10.0; // OK: 因为 length 是公有的
	cout << "Length of line : " << line.length << endl;
	return 0;
}

在此代码中,length是用public修饰,我们可以通过Init方法对length进行修改,也可以直接通过对成员变量length进行修改。

2.private修饰成员举例

#include <iostream>

using namespace std;

class Box
{
public:
	void setLength(double len)
	{
		length = len;
	}
	double getLength()
	{
		return length;
	}

private:
	double length;
};



// 程序的主函数
int main()
{
	Box box;
	// 不使用成员函数设置宽度
	box.length = 10.0; // Error: 因为 length 是私有的
	box.setLength(10.0);  // 使用成员函数设置宽度
	cout << "Length of box : " << box.getLength() << endl;

	return 0;
}

在直接对length访问时,报错,但是使用setLength方法的时候不报错。

3.protected修饰成员举例

#include <iostream>
using namespace std;

class Box
{
protected:
	double length;
};

class SmallBox :Box // SmallBox 是子类
{
public:
	void setSmallLength(double wid)
	{
		length = wid;
	}
	double getSmallLength(void)
	{
		return length;
	}
};

// 程序的主函数
int main()
{
	SmallBox box;

	// 使用成员函数设置宽度
	box.setSmallLength(5.0);
	cout << "length of box : " << box.getSmallLength() << endl;

	return 0;
}

在该代码中,SmallBox为子类,子类中的方法可以访问Box中被protected修饰的length.

六、封装

封装,继承,多态是面向对象语言的三大特性,不仅仅是C++而是包括Java、Python等面向对象语言都有的共性。

封装是将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来 和对象进行交互。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值