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吧,不是本节重点。
6:声明成员函数为内联函数
内联函数是一种以关键字inline
修饰的函数。当编译器处理内联函数调用时,不会像处理普通函数那样进行函数调用的开销(如入栈、出栈操作等),而是直接将函数体的代码插入到函数调用处。可以近似理解成宏,但又和宏有区别。
1:为什么有内联函数
1:提高执行效率:
避免函数调用时的入栈、出栈等开销,直接将函数体代码插入调用处,对于频繁调用的简单函数,能显著减少执行时间,提升程序运行速度。
2:增强代码可读性:
可以把具有特定功能的代码封装成函数形式,使主程序逻辑更清晰,即使是简单操作,也能让代码结构更有条理,易于阅读和理解。
3:优化小型函数:
针对小型的、功能单一的操作,如简单数学运算、类型转换等,内联函数在保证代码模块化的同时,能有效优化程序性能,减少不必要的函数调用开销。
2:内联函数和宏的区别
1:语法方面
- 内联函数 :使用
inline
关键字修饰,有完整的函数声明和函数体,遵循函数语法规则。 - 宏定义 :通过
#define
指令定义,只是简单的文本替换,无函数声明和函数体。
2:调用机制
- 内联函数:编译时将函数体插入调用处,遵循函数调用流程,有参数传递和局部变量创建等。
- 宏定义:预处理时进行文本替换,不涉及函数调用过程及相关操作。
3:参数检查
- 内联函数:编译时进行严格的参数类型检查,类型不匹配会报错。
- 宏定义:只是文本替换,不进行参数类型检查,可能导致潜在错误。
4:可读性与调试
- 内联函数:代码可读性好,可像普通函数一样调试。
- 宏定义:可读性相对较差,无法像函数那样调试。
5:作用域和生命周期
- 内联函数:具有普通函数的作用域和生命周期,局部变量在每次调用时重新创建和销毁。
- 宏定义:作用域从定义处到文件末尾,预处理后不存在宏定义本身概念。
6:可维护性
- 内联函数:修改功能只需在定义处修改,维护方便。
- 宏定义:修改功能需在所有使用处检查修改,易遗漏,维护困难。