目录
面对过程与面向对象的认识
c语言是面向过程的,关注的是过程,分析出求解问题的过程,通过函数调用逐步解决问题。
c++是面向对象的,关注的是对象,讲一件事情拆分成不同的对象,靠对象之间的交互完成。
比如要实现一个外卖系统,用c语言写的话,会关注过程上怎样去实现它:上架商品、点外卖、派送、点评……。用c++的话,就关注对象:商家、骑手、用户。然后把有关商家、骑手、用户的信息归纳到各自的类中。
类的引入
在c语言中,结构体中只能定义变量,不能定义函数。在c++中,结构体不仅可以定义变量,而且还可以定义函数。
//c++中struct可以定义变量跟函数
struct student
{
void Init(const char*name, const char* sex,int age)
{
strcpy(_name, name);
strcpy(_sex, sex);
_age = age;
}
void Print()
{
cout << _name << " " << _sex << " " << _age << endl;
}
char _name[20];
char _sex[3];
int _age;
};
int main()
{
student s1;
s1.Init("张三", "男", 20);
s1.Print();
return 0;
}
上面结构体的定义,在c++中更喜欢用class来代替。
类的定义
class ClassName
{
//这里面写成员函数和成员变量
}; //后面必须要有分号
class为定义类的关键字,ClassName为类的名字,这个名字可以随便取,但也要注意命名规范,{}中为类的主体。
//创建一个叫studen的学生类
class student
{
public:
void Init(const char*name, const char* sex,int age)
{
strcpy(_name, name);
strcpy(_sex, sex);
_age = age;
}
void Print()
{
cout << _name << " " << _sex << " " << _age << endl;
}
private:
char _name[20];
char _sex[3];
int _age;
};
int main()
{
student s1;
s1.Init("张三", "男", 20);
s1.Print();
return 0;
}
类的访问限定符及封装
访问限定符:
c++的封装方式:是用类将对象的属性与方法结合在一块,让对象更加完善。通过访问限定符来选择一些接口提供给外部的用户使用,如要给外部访问的就设置成public,不想让外部访问的就设置成private。
【访问限定符说明】
1. public修饰的成员在类外可以直接被访问
2. protected和private修饰的成员在类外不能直接被访问(此阶段protected可以理解成跟private是类似的,到了继承才有区别)
3. 访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止
4. class的默认访问权限为private,struct的默认权限为public(因为struct要兼容c)
注:使用private私有限定符,只是限制在类外不能访问,但在类内是可以访问的。就好比一把锁,锁住房门后,外面的人就不能进入房子里面了,但在房子里面的人是可以随便使用房子里面的东西的。
封装:
封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互。
封装是为了更好的管理,可以这样理解:我们是如何管理列车的呢?如果我们什么都不管的话,或许就会跟印度火车一样挂满人。
于是我们就建立一个高铁站,把这些东西全部给封装起来。只开放售票通道,其他都不用知道。可以在网上购票完成后,通过安检后,进入候车处等待检票时间到,在检票机上刷身份证通过后即可进入。经过这几道程序后便能井然有序的乘坐列车。类也是一样的,不想让别人看到或使用类成员的话就可以用privare、protected把成员封装起来,只开放一些成员函数来对类中的成员进行合理的分配。因此封装本质上就是一种管理。
类的实例化
用类创建一个对象的过程,称为类的实例化。
1、类只是一个模型一样的东西,定义出类有哪些成员,定义出的类并不会被分配实际的内存空间来存储它。(就像一张建筑图纸,并没有实际的占地空间,只是告诉我们有什么东西可以来建造一栋房子)。
2. 一个类可以实例化出多个对象,实例化出的对象占用实际的物理空间来存储类成员变量。
做个比方。类实例化出的对象就像在现实中使用建筑图纸建造出的房子,类就像是设计图,只设计出需要什么东西,但是并没有实体的建筑存在,实例化出的对象才能存储数据,占用物理空间。
class student
{
public:
void Init(char name[], char sex[], int age)
{
strcpy(_name, name);
strcpy(_sex, sex);
_age = age;
}
void Print()
{
cout << _name << " " << _sex << " " << _age << endl;
}
char _name[20];
char _sex[3];
int _age;
};
int main()
{
//实例化出多个对象
student s1;
s1.Init("张三","男",20);
student s2;
s2.Init("李四", "男", 21);
return 0;
}
类对象的存储方式
先来看看类的大小是多少。
class A
{
public:
void setA(char a, int b)
{
_a = a;
_b = b;
}
void PrintA()
{
cout << _a << " " << _b<<endl;
}
private:
char _a;
int _b;
};
类既有成员函数又有成员变量,一个类的大小是如何计算的呢?
得出的结果是8,咦?一个类中有成员函数还有成员变量怎么实例化出的对象大小却只有8呢?
其实不难理解,对象中存放的只是成员变量,并没有存放成员函数,而是把成员函数另外放到公共代码区里的。调用成员函数的时候都是同一个函数。
为什么不把成员函数跟成员变量放一起呢?试想一下每个对象的成员变量是不一样的,但成员函数却是一样的,如果按照此存储方式存储的话每实例化出一个对象就会存储一份相同的代码,岂不是会造成空间的浪费吗。
this指针的引出
class Date
{
public:
void InitDate(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
void PirntDate()
{
cout << _year << " " << _month << " " << _day << endl;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
//this指针的引出
Date d1;
d1.InitDate(2022, 6, 14);
d1.PirntDate();
Date d2;
d2.InitDate(2002, 6, 15);
d2.PirntDate();
return 0;
}
竟然它们调用的是同一个函数,那为什么打印出来的东西却是不一样的呢?
因为有一个this的隐含指针,C++编译器给每个“非静态的成员函数“增加了一个隐藏的指针参
数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有成员变量的操作,都是通过该指针去访问。只不过所有的操作对用户是透明的,即不需要用户来传递,编译器会自动完成。