在C语言基础上的C++第二章(类和对象)

1:面向对象的程序设计

我们学习过的C语言是一种面向过程的程序设计。思想是把问题分割成一个个函数,然后用主函数把它们串联起来。

而C++是面向对象的程序设计。面向对象的程序设计(Object - Oriented Programming,简称 OOP)是一种编程范式,它以对象为核心来组织程序结构。他具有以下四个特征:

1:抽象性:许多实体的共性产生类。

2:封装性:类将数据和操作封装为用户自定义的抽象数据类型。

3:继承性:类能被重复利用,具有继承(派生)机制。

4:多态性:具有动态联编机制。

2:类的定义

类是一种用户定义的数据类型,它就像是一个蓝图或者模板,用于创建对象。例如,在建造房子时,建筑图纸就是 "类",而根据这个图纸建造出来的一个个具体的房子就是 "对象"。

1:从结构体到类

C语言里的结构体,以一个学生为例

cpp 复制代码
struct student{
int no;//学号
char name[20];//姓名
float score;//分数
};

下面我们在C++里面定义一个类,看看有什么相同之处

cpp 复制代码
class student{
int no;
char name[20];
float score;
void display(){
  cout<<"学号"<<no<<endl;
  cout<<"姓名"<<name<<endl;
  cout<<"分数"<<score<<endl;
  }
};

标准C里面是不允许在结构体里面声明函数的,但是C++的类的定义不仅包含数据而且包含对数据进行操作的函数。这点与C有着本质区别,很好地体现了C++面向对象的特点。

这种将数据和对数据进行操作的函数放在一起的做法称为封装。

封装在类中的成员(数据和函数)与外界是无法接触的,这样十分安全,但如果完全与外界隔绝,这样的类就无实际意义了。就像display函数,外界无法使用。所以我们一般情况下,会把数据隐藏起来,而把对数据的操作作为与外界的公共的接口与外界联系。所以我们可以这样定义

cpp 复制代码
class student{
private://以下成员是私有的
  int no;
  char name[20];
  float score;
public://以下成员是公有的
void display(){
  cout<<"学号"<<no<<endl;
  cout<<"姓名"<<name<<endl;
  cout<<"分数"<<score<<endl;
  }
};

如果在类里面不指定private和public,那么默认都是private私有的。

但是在struct里面默认都是公有的。

2:类的格式

class 类名

{ private:

数据成员和成员函数;

protected:

数据成员和成员函数;

public:

数据成员和成员函数;

}:

3:对象的定义

类是抽象的,定义的student类不是指哪个特定学生。利用类可以像定义变量一样定义对象。

例如

cpp 复制代码
class student{
private:
  int no;
  char name[20];
  float score;
public:
void display(){
  cout<<"学号"<<no<<endl;
  cout<<"姓名"<<name<<endl;
  cout<<"分数"<<score<<endl;
  }
};
class student s1;
student s2;

1:对象的定义格式

我们可以使用

class 类名 对象名 //class student s1;

这是第一种方法,符合C语言的写法

还可以使用

类名 对象名//student s2;

这是第二种定义方法,是C++的特色

2:对象成员的访问

和C语言中一样我们对于对象名使用"."符合来访问,对于对象的指针我们使用"->"来访问。

在这里就不多说了。

4:类的成员函数

一般的函数

cpp 复制代码
void display(student s){
  cout<<"学号"<<s.no<<endl;
  cout<<"姓名"<<s.name<<endl;
  cout<<"分数"<<s.score<<endl;
  }

在一般函数中,不能直接使用数据成员了,而要加上对象名称才能使用。

但成员函数是在类中定义的,可以直接使用数据成员。

1:this指针

在 C++ 中,this指针是一个隐含于每一个非静态成员函数中的特殊指针。它指向调用该成员函数的对象。简单来说,当你调用一个对象的成员函数时,编译器会自动将这个对象的地址通过this指针传递给成员函数。

例如定义一个student的变量s1

cpp 复制代码
void display(){
  cout<<"学号"<<this->no<<endl;
  cout<<"姓名"<<this->name<<endl;
  cout<<"分数"<<this->score<<endl;
  }
};

相当于执行了

cpp 复制代码
void display(){
  cout<<"学号"<<s1.no<<endl;
  cout<<"姓名"<<s1.name<<endl;
  cout<<"分数"<<s1.score<<endl;
  }
};

2:成员函数的重载

成员函数与一般函数一样,也可以重载

看以下程序

cpp 复制代码
#include<iostream>
using namespace std;

class student {
public:
	void set()
	{
		cout << "请输入学号,姓名,分数" << endl;
		cin >> no >> name >> score;
	}
	void set(int n,const char na[], float s)
	{
		no = n;
		strcpy(name, na);
		score = s;
	}
	void display()
	{
		cout << "学号" << no << endl;
		cout << "姓名" << name << endl;
		cout << "分数" << score << endl;
	}
private:
	int no;
	char name[20];
	float score;
};

int main()
{
	student s1, s2;
	s1.set();
	s2.set(999, "伪人",88.8);
	s1.display();
	s2.display();
	return 0;
}

set函数进行重载。

注意:我们传递的"伪人"是一个常量字符串,需要使用const来保证可读性

3:在类外定义成员函数

类中的所有成员函数一般都需要在类中声明,但是如果成员函数体比较大,在类里面定义非常不方便,所有我们可以在类的外面定义成员函数

格式如下

返回值类型 类名::成员函数名(参数列表)

{ // 函数体 }

看下面例子,将上述代码这样定义

在类里面进行函数的声明,在类外面进行函数体的书写。

cpp 复制代码
class student {
public:
	void set();
	void set(int n, const char na[], float s);
	void display();
private:
	int no;
	char name[20];
	float score;
};
void student::set()
{
	cout << "请输入学号,姓名,分数" << endl;
	cin >> no >> name >> score;
}

void student::set(int n, const char na[], float s)
{
	no = n;
	strcpy(name, na);
	score = s;
}
void student::display()
{
	cout << "学号" << no << endl;
	cout << "姓名" << name << endl;
	cout << "分数" << score << endl;
}

5:运算符::(作用域运算符)

引用别人的blog吧,不是本节重点。

https://blog.csdn.net/sangyongqi/article/details/139770556?ops_request_misc=%257B%2522request%255Fid%2522%253A%252266682c2d07aa2536bae9814fd325f1a5%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=66682c2d07aa2536bae9814fd325f1a5&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-1-139770556-null-null.142^v100^pc_search_result_base8&utm_term=%3A%3A%E8%BF%90%E7%AE%97%E7%AC%A6&spm=1018.2226.3001.4187

6:声明成员函数为内联函数

内联函数是一种以关键字inline修饰的函数。当编译器处理内联函数调用时,不会像处理普通函数那样进行函数调用的开销(如入栈、出栈操作等),而是直接将函数体的代码插入到函数调用处。可以近似理解成宏,但又和宏有区别。

1:为什么有内联函数

1:提高执行效率

避免函数调用时的入栈、出栈等开销,直接将函数体代码插入调用处,对于频繁调用的简单函数,能显著减少执行时间,提升程序运行速度。

2:增强代码可读性

可以把具有特定功能的代码封装成函数形式,使主程序逻辑更清晰,即使是简单操作,也能让代码结构更有条理,易于阅读和理解。

3:优化小型函数

针对小型的、功能单一的操作,如简单数学运算、类型转换等,内联函数在保证代码模块化的同时,能有效优化程序性能,减少不必要的函数调用开销。

2:内联函数和宏的区别

1:语法方面
  • 内联函数 :使用inline关键字修饰,有完整的函数声明和函数体,遵循函数语法规则。
  • 宏定义 :通过#define指令定义,只是简单的文本替换,无函数声明和函数体。
2:调用机制
  • 内联函数:编译时将函数体插入调用处,遵循函数调用流程,有参数传递和局部变量创建等。
  • 宏定义:预处理时进行文本替换,不涉及函数调用过程及相关操作。
3:参数检查
  • 内联函数:编译时进行严格的参数类型检查,类型不匹配会报错。
  • 宏定义:只是文本替换,不进行参数类型检查,可能导致潜在错误。
4:可读性与调试
  • 内联函数:代码可读性好,可像普通函数一样调试。
  • 宏定义:可读性相对较差,无法像函数那样调试。

5:作用域和生命周期

  • 内联函数:具有普通函数的作用域和生命周期,局部变量在每次调用时重新创建和销毁。
  • 宏定义:作用域从定义处到文件末尾,预处理后不存在宏定义本身概念。
6:可维护性
  • 内联函数:修改功能只需在定义处修改,维护方便。
  • 宏定义:修改功能需在所有使用处检查修改,易遗漏,维护困难。
相关推荐
程序猿方梓燚2 分钟前
跨年烟花C++代码
android·开发语言·c++
游王子26 分钟前
Python学习(5):数据结构
开发语言·数据结构·python·学习
大G哥43 分钟前
【Lua】元表与元方法
开发语言·lua
檀越剑指大厂1 小时前
【Python系列】处理空请求体Body
开发语言·python
海风极客1 小时前
Go小技巧&易错点100例(十九)
开发语言·后端·golang
Dola_Pan1 小时前
C语言:调试的概念和调试器的选择
c语言·开发语言
南宫生1 小时前
力扣-数据结构-8【算法学习day.79】
java·数据结构·学习·算法·leetcode
计算机学姐1 小时前
基于Python的社交音乐分享平台
开发语言·vue.js·python·mysql·django·flask·pip
2401_871151071 小时前
1月第三讲:Java子线程无法获取Attributes的解决方法
java·开发语言
武昌库里写JAVA1 小时前
mysql乱码、mysql数据中文问号
java·开发语言·spring boot·学习·课程设计