C++(一)、C++类的介绍

C++(一)、C++类的介绍

大四应届狗,学的电气,不想去爬电线杆子;
现在是9月23号,想进阿里的软件测试开发,自学C++、操作系统、Linux、数据结构;
这一部分记录一下C++的学习过程,坐稳了,小车车要开动喽~~

//入门小奶狗,权杖大神带路哦~
https://blog.csdn.net/eliminatedacmer/article/details/79254433
https://blog.csdn.net/weixin_43711569/article/details/103465575
https://blog.csdn.net/qq_18837111/article/details/107301243

1、类和对象

在c语言中,程序是由若干的函数以及变量组成的,它们之间并没有很严格的关系,这就导致了当程序规模逐渐变大之后,就不易于程序的扩充以及维护。另外,当我们想要复用之前程序中的一些代码片段时,函数中的变量使得我们很难将其从程序中抽离出来。总之,结构化程序设计使得我们的程序难以扩充、难以维护、难以重用。【这就叫迭代,成年人的世界中,迭代真的是一件很美好的事】

C++在c语言的基础上增加了面向对象程序设计(Object-oriented programming,OOP)的机制,而面向对象的这种机制恰好解决了c语言结构化设计的这种缺陷。简单来说,在面向对象程序设计中,我们可以依照以下的设计方法:

我们将某类客观事物的共同特点(属性)归纳出来,形成一个数据结构,可以用多个变量描述事物的属性。
将这类事物所能进行的行为也归纳出来,形成函数,这些函数就用来操作数据结构。
然后通过某种方式将这些数据结构与函数捆绑封装起来,从而形成一个类。
需要注意的是,被封装的函数只能访问与它封装在一起的数据结构,反之,这些数据结构也只能被与它封装在一起的函数所操作。这样就使得某一类事物的数据结构只能由与之封装的函数进行操作,而其它函数是无法访问其数据结构的。

1.1、类的定义

是用户自定义的数据类型。
C++一个类定义的形式如下:
class 类名
{
成员列表
};
成员列表是类成员的集合,数目可以任意多, 一对 { } 是成员列表边界符,与成员列表一起成为类体。类体后面必须用 ; 结束。
1.每个类可以没有成员,也可以有多个成员。
2.类成员可以是数据或函数。
3.所有成员必须在类内部声明,一旦类定义完成后,就没有任何其他方式可以再增加或减少成员。

在面向对象程序设计中,一般将变量(数据)隐蔽起来,外部不能直接访问。把成员函数作为对外界的接口,通过成员函数访问数据,可能一开始学习的时候不太理解,这个我们在后面会经常用到,请耐心观看。

类中如果有成员函数,则声明是必须的,而定义是可选的,什么意思呢,请看下例:

在类内部定义函数体
class 类名
{
返回类型 函数名(形参列表)
{
函数体
}
};

在类外部定义函数体
class 类名
{
返回类型 函数名(形参列表);
};
返回类型 类名 :: 函数名(形参列表)
{
函数体
}

看到这里会产生一个问题,那就是这两种定义方法到底有什么区别,或者根本没有区别。
其实它们还是有区别的,类内部定义的函数,程序在要调用它的时候会把它当作是一个内联函数,内联函数的好处是调用速度更快,但是会占用额外的内存空间,每调用一次都相当于定义一次。而外部定义的函数,就不会被当作内联函数。对于一些要用到递归的函数,定义成内联函数肯定是不合理的。因此建议使用第二种方法定义成员函数。

类的定义一般放在程序文件开头,或者放到头文件中被程序文件包含,当然也可以放在局部作用域里。这里有必要提一下,c++规定,在局部作用域中声明的类,成员函数必须是函数定义形式,不能是原型声明。

类相当于一种新的数据类型,数据类型不占用存储空间,用类型定义一个实体的时候,才会为它分配存储空间。

1.2、创建对象

普通创建
class Rectangle {
public:
	double length;//长
	double weight;//宽
    
	void init(double length_,double weight_) {//设置长和宽
		length = length_;//设置长
		weight = weight_;//设置宽
	}
	double Area(){//计算面积
		return length * weight;
	}
	double Perimeter() {//计算周长
		return 2 * (length + weight);
	}
};//分号不可省略
/*
//普通创建
*/
int main() {
	Rectangle r;//声明一个对象
	double length = 10.0;
	double weight = 10.0;
	r.init(length, weight);//初始化对象
	cout << "矩形面积为:" << r.Area() << endl;
	cout << "矩形周长为:" << r.Perimeter() << endl;
	return 0;
}

通过指针创建
int main() {
	double length;//长
	double weight;//宽
	Rectangle *r;//声明一个对象指针
	r = new Rectangle;//为对象动态分配内存空间
	r->init(length, weight);//初始化对象
	cout << "矩形面积为:" << r->Area() << endl;
	cout << "矩形周长为:" << r->Perimeter() << endl;
    delete r;//释放动态分配的空间
	return 0;
}

1.3、访问数据成员

类的对象的公共数据成员(public)可以使用直接成员访问运算符.或->来访问。

使用 . 访问
int main() {
	Rectangle r;//声明一个对象
	double length = 10.0;
	double weight = 10.0;
	r.init(length, weight);//初始化对象
	cout << "矩形长为:" << r.length << endl;
	cout << "矩形宽为:" << r.weight << endl;
	return 0;
}

使用 -> 访问
int main() {
	double length;//长
	double weight;//宽
	Rectangle *r;//声明一个对象指针
	r = new Rectangle;//为对象动态分配内存空间
	r->init(length, weight);//初始化对象
	cout << "矩形长为:" << r->length << endl;
	cout << "矩形宽为:" << r->weight << endl;
	delete r;//释放动态分配的空间
	return 0;
}

1.4、对象的内存分配

*** 类不占用内存
*** 对象占用内存

int main() {
	double length;//长
	double weight;//宽
	Rectangle r;//声明一个对象
	cout << "sizeof(Rectangle)=" << sizeof(Rectangle) << endl;
	return 0;
}

运行得到:

sizeof(Rectangle)=16

C++中 的本质和C中 int 是一样的
对象int X;中 的X是一样的
所以,每一个对象都单独占用内存,且相互不影响

2、成员函数

2.1、成员函数
内联函数

函数在class类中直接定义,很少这样使用
内联函数一般不是我们所期望的,它会将函数调用处用函数体替代,所以建议在类体内部对成员函数作声明,而在类体外部进行定义,这是一种良好的编程习惯。

class Rectangle {
public:
	double length;//长
	double weight;//宽
    
	void init(double length_,double weight_) {//设置长和宽
		length = length_;//设置长
		weight = weight_;//设置宽
	}
	double Area(){//计算面积
		return length * weight;
	}
	double Perimeter() {//计算周长
		return 2 * (length + weight);
	}
};//分号不可省略
外联函数

通过 ::,可以将函数定义在类的外部,增加代码的可读性

void Rectangle::init(double length_, double weight_) {
	length = length_;
	weight = weight_;
}
double Rectangle::Area() {
	return length * weight;
}
double Rectangle::Perimeter() {
	return 2 * (length * weight);
}

基本格式

返回值类型 类名::函数名(参数表){
    函数体
}

外联函数转变为内联函数----inline
//inline将外联函数转变为内联函数
inline void Rectangle::init(double length_, double weight_) {
	length = length_;
	weight = weight_;
}
double Rectangle::Area() {
	return length * weight;
}
double Rectangle::Perimeter() {
	return 2 * (length * weight);
}

2.2、类成员的访问权限和封装

C++ 通过 public、protected、private 三个关键字来控制成员变量和成员函数的访问权限,它们分别表示公有的、受保护的、私有的,被称为成员访问限定符。所谓访问权限,就是你能不能使用该类中的成员。

在类的内部(定义类的代码内部),无论成员被声明为 public、protected、private,都是可以互相访问的,没有访问权限的限制

在类的外部(定义类的代码之外),只能通过对象访问成员,并且通过对象只能访问 public 属性的成员,不能访问 private、protected 属性的成员。

private 关键字的作用在于更好地隐藏类的内部实现,该向外暴露的接口(能通过对象访问的成员)都声明为 public,不希望外部知道、或者只在类内部使用的、或者对外部没有影响的成员,都建议声明为 private。

根据 C++ 软件设计规范,实际项目开发中的成员变量以及只在类内部使用的成员函数(只被成员函数调用的成员函数)都建议声明为 private,而只将允许通过对象调用的成员函数声明为 public。

3、构造函数、析构函数

构造函数

(到现在也看得不是很懂~~//卑微)
在 C++ 中,有一种特殊的成员函数,它的名字和类名相同,没有返回值,不需要用户显式调用(用户也不能调用),而是在创建对象时自动执行。这种特殊的成员函数就是构造函数(Constructor)。

构造函数必须是 public 属性的,否则创建对象时无法调用。

构造函数没有返回值,因为没有变量来接收返回值,即使有也毫无用处,这意味着:

不管是声明还是定义,函数名前面都不能出现返回值类型,即使是 void 也不允许;
函数体中不能有 return 语句。

析构函数

创建对象时系统会自动调用构造函数进行初始化工作,同样,销毁对象时系统也会自动调用一个函数来进行清理工作,例如释放分配的内存、关闭打开的文件等,这个函数就是析构函数。

析构函数(Destructor)也是一种特殊的成员函数,没有返回值,不需要程序员显示调用(也没法显示调用),而是在销毁对象时自动执行。 构造函数的名字和类名相同,而析构函数的名字是在类名前加一个 ~ 符号。

注意:析构函数没有参数,不能被重载,因此一个类只能有一个析构函数。如果用户没有定义,编译器会自动生成一个默认的析构函数。

函数名是标识符的一种,原则上标识符的命名中不允许出现 ~ 符号,在析构函数的名字中出现的~可以认为是一种特殊情况,目的是为了和构造函数的名字加以对比和区分。

C++ 中的 new 和 delete 分别用来分配和释放内存,它们与 C 语言中 malloc()、free() 最大的一个不同之处在于:用 new 分配内存时会调用构造函数,用 delete 释放内存时会调用析构函数。构造函数和析构函数对于类来说是不可或缺的,所以在 C++ 中鼓励使用 new 和 delete。

4、静态成员

4.1、静态数据成员

对象的内存中包含了成员变量,不同的对象占用不同的内存,这使得不同对象的成员变量相互独立,它们的值不受其他对象的影响。

可是有时候我们希望在多个对象之间共享数据,对象 a 改变了某份数据后对象 b 可以检测到。共享数据的典型使用场景是计数,以前面的 Student 类为例,如果我们想知道班级中共有多少名学生,就可以设置一份共享的变量,每次创建对象时让该变量加 1。

在 C++ 中,我们可以使用静态成员变量来实现多个对象共享数据的目标。静态成员变量是一种特殊的成员变量,它被关键字 static 修饰。

4.2、静态成员函数

在类中, static 除了可以声明静态成员变量,还可以声明静态成员函数。普通成员函数可以访问所有成员(包括成员变量和成员函数),静态成员函数只能访问静态成员。

编译器在编译一个普通成员函数时,会隐式地增加一个形参 this,并把当前对象的地址赋值给 this,所以普通成员函数只能在创建对象后通过对象来调用,因为它需要当前对象的地址。而静态成员函数可以通过类来直接调用,编译器不会为它增加形参 this,它不需要当前对象的地址,所以不管有没有创建对象,都可以调用静态成员函数。

普通成员变量占用对象的内存,而静态成员函数没有 this 指针,不知道指向哪个对象,无法访问对象的成员变量,也就是说静态成员函数不能访问普通成员变量,只能访问静态成员变量。

普通成员函数必须通过对象才能调用,而静态成员函数没有 this 指针,无法在函数体内部访问某个对象,所以不能调用普通成员函数,只能调用静态成员函数。

静态成员函数与普通成员函数的根本区别在于:普通成员函数有 this 指针,可以访问类中的任意成员;而静态成员函数没有 this 指针,只能访问静态成员(包括静态成员变量和静态成员函数)。

在 C++ 中,静态成员函数的主要目的是访问静态成员。和静态成员变量类似,静态成员函数在声明时要加 static,在定义时不能加 static。静态成员函数可以通过类来调用(一般都是这样做),也可以通过对象来调用。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值