今天给大家带来类与对象的学习分享。认真做好每一篇博客,就是博主的愿景。希望接下来的内容,对大家有帮助!
1.类的产生
从C语言进入到C++,C语言是面向过程的,C++是面向对象的。
就好比,拿网购来说。C++面向对象,对象就分作顾客,商家,以及快递员。 C++中,把对象确定好了,将事情拆分成一个个对象,通过对象之间相互作用去实现事情。
在C语言中,我们学了结构体struct,这便是C++类引出的地方。
在C语言中,struct里面只能定义成员变量,不能定义成员函数。于是在C++中,通过改进,可以引出成员函数。 再由于struct,我们又引出了一个专门用来表示类的字符就是“class”。
2.类的定义
那么,类该如何去定义呢?
class classname
{
//类体:类体中的内容就是类的成员。
//类中的变量称为成员变量,类中的函数称为成员函数
};(分号不要漏)
这里再说一下对于成员函数的规定:
1.我们可以选择把成员函数的声明和定义都放在一起
2.也可以选择将成员函数的声明和定义分离,但是在定义函数时,必须要带上 “类名::” 才可以。
//这是第一种情况
class student
{
public:
void show()
{
cout << _name << _age << _sex << endl;
}
private:
char _name;
int _age;
char _sex;
};
//这是第二种情况
//在头文件中只包含了声明,没写出定义
//student.h
class student
{
public:
void show()
private:
char _name;
int _age;
char _sex;
};
//student.cpp
#include"student.h"
void student::show() //在这类,注意一定要加上类名::的形式
{
cout << _name << _age << _sex << endl;
}
3.类的访问限定符
在上面,已经写了关于类的一点代码。这里,在对上面的代码两个点进行解释。
第一个就是private和public的点。
在C++中,通过访问权限选择性的将接口给用户使用,因此有了类的访问符限定。
分为三个:public(公有),private和protected(私有,保护)。
public修饰的成员在类外可以直接被访问,private和protected修饰的成员在类外不可以直接被访问。
通过上面的代码,我们可以推测出类的访问限定符的作用域,即从该访问限定符出现的位置开始直到下一个访问限定符出现时为止,如果后面没有访问限定符,作用域就到 } 即类结束。、
那么在类外想要访问到类里private成员该怎么做呢?
我们还是用“类名::”的方式。
//比方这是在类外
void student::show() //在这类,注意一定要加上类名::的形式
{
cout << _name << _age << _sex << endl;
}
这里再提及一下,在C++中,class的默认访问权限为private,struct为public。因为C++兼容C,C++中struct既可以做结构体也可以做类使用,所以把struct规定为public。
第二个就是对成员变量进行优化
好比说上面的成员函数Init,如果我们成员变量前面没有加上“_”的话,是不是就会产生歧义误解。( name = name 就容易产生误会,加上_后,_name = name,就很容易区分了)
所以呢,在定义成员变量的时候,我们可以加上前缀或者后缀来区分开形参,避免产生歧义。
4.类的实例化
定义:用类的类型去创建对象的过程,叫作类的实例化。
int main()
{
student stu;
//student._age = 20;
stu._age = 20;
}
借上面的代码,在这我们就是创建了一个对象stu,我们才可以
对这个对象里面的_age进行修改,而不能直接对student进行修改,
因为它只是一个类名,还不是一个对象,不能对其进行修改
这就好比我们去造房子,student就是施工图纸,stu就是通过施工图纸建造出来的一个房子。我们只能对这个房子内部进行修改,而不是去改变施工图纸。
类只是对对象的描述,类似于模型,没有实际的空间来存储它。一个类可以实例化出多个对象,实例化出的对象 占用实际的物理空间,存储类成员变量
5.计算类的大小
class student
{
public:
void show()
{
cout << _name << _age << _sex << endl;
}
public:
char* _name;
int _age;
char* _sex;
};
int main()
{
student s1;
s1.show();
student s2;
s2.show();
student s3;
s3.show();
}
还是这个代码,这个类究竟是多大呢?
我们创建多个对象,同时调用show函数。我们可以发现调用的过程是相同的,不同的是不同对象里面的不同成员变量。但成员函数,归根结底还是成员变量,成员函数调用的过程是一样的!
所以,实际上我们计算类的大小,就是该类中”成员变量”之和。(这里注意成员变量对齐的规则)
我们把成员函数放在一个公共区,对象中只存放成员函数的地址方便访问。
这里给大家画了一个图,形象展示:
6.this指针
引入this指针之前,我们想想这个代码:
//借用前面的代码
int main()
{
student s1;
s1.show();
student s2;
s2.show();
student s3;
s3.show();
}
//在这里,3次调用show函数,为什么可以精确到s1,s2,s3?
//实际上,这里就是利用了this指针。
C++编译器给每个“非静态成员函数”增加了一个隐藏的指针参数,让该指针指向当前对象。在函数体中所有“成员变量”的操作,都是通过该指针去访问,即this指针。用户不需要去传递,编译器会自动完成。
这里通过s1调用show函数来给大家再详细的看一看:
void show(student* this)
{
cout << this->_name << this->_age << this->_sex << endl;
}
接下来说几个this指针的特性:
this指针的特性
1.this指针的类型是类的类型+const+this,也就是this指针是不能被修改的
2.this指针只在成员函数内部使用
3.this指针是成员函数的第一个隐含的形参。对象在调用成员函数时,会将对象的地址作为实参传给成员函数this形参处接收。
最后,分析两个题目:
// 1.下面程序编译运行结果是? A、编译报错 B、运行崩溃 C、正常运行
class A
{
public:
void Print()
{
cout << "Print()" << endl;
}
private:
int _a;
};
int main()
{
A* p = nullptr;
p->Print();
return 0;
}
//这一题的答案是C
可千万不要被p初始化为空指针而迷惑了。在这,p是一个对象,
我们仅仅是通过p这个对象访问到类里面的成员函数。
之前,我们说了,成员函数是放在公共区的,我们可以对其进行访问!
好,不管能不能接受,我们先看下一个题。
// 2.下面程序编译运行结果是? A、编译报错 B、运行崩溃 C、正常运行
class A
{
public:
void PrintA()
{
cout<<_a<<endl;
}
private:
int _a;
};
int main()
{
A* p = nullptr;
p->PrintA();
return 0;
}
//这一题的答案是B
首先,这里调用了PrintA函数其实是没问题的,与上面的情况一样。
但调用这个成员函数之后,我们通过p对象去访问了_a这个成员变量,
这里就出现了问题,因为p是空指针,用p就解引用访问_a这个成员变量
就不行,成员变量是在p里面的,不在公共区,情况不同,
因此会出现运行崩溃!
(可以参考计算类的大小那里,我给大家画的图!)
可能说到这,大家还是会觉得不理解。为啥空指针可以访问到成员函数但是不能访问到成员变量。 那么,我给大家打个比方:比方说,这个类是一个小区,对象就是里面的居民。成员变量是一间间房子,而成员函数就相当于公共的健身房。 作为这个类的对象,意味着,我们是这个小区的居民。(不为空指针也就意味着我们可以随意访问我们的成员变量和成员函数)。当我们为空指针,也就相当于我们不再是小区里的居民,我们或许可以去公共的健身房(也就是访问成员函数),但我们不能再进入到居民房,也就是不再具备访问成员对象的条件。
这个比方,希望能帮助大家理解这两个题!
好了,这就是我对于类与对象(上)的分享,也是用了很多心思在上面。 但愿能够给到大家帮助,也渴望得到大家的支持。你们的支持是我更新博客的动力!!
“赠人玫瑰,手留余香”, 不妨留下一键三连呗!!!