C++——类与对象(上)

        C++与C语言区别中,最大的三个特征就是封装、继承和多态,其中类就是C++实现封装的一种形式。为了让使用者不能读取到我们的数据,只能通过我们编写的函数来操作对应的数据,实现这个要求就用到了C++中非常重要的类。

目录

       一、总体介绍

        二、访问限定符

        三、类域

        四、实例化

        五、this指针

        实践:


       一、总体介绍

         下面是我编写的一个简单的学生类第一次接触C++代码的人一看一定会蒙圈,但是没关系,接下来我会一点点分析每个部分是什么,他的作用是什么。从这里我们先认识到,C++中类的定义方式和C语言中结构体的定义方式是非常相似的,都是类型名+名字+{}+;组成的,其中类当中比结构体多出了一些函数,这些函数我们称为这个类的成员函数,类里的变量我们称为这个类的成员变量。

        而在C++中同样把struck结构体进行了升级,同样可以在结构体内部定义函数,class和struck的区别在于,如果不加访问限定符时,class的默认类型是privatestruck的默认类型是public。

class student
{
public:
	student(string n= "wang", int a = 20, char s = 'M')
	{
		name = n;
		age = a;
		sex = s;
	}
	void print()
	{
		cout << "name:" << name << " age=" << age << " sex=" << sex << endl;
	}
private:
	string name;
	int age;
	char sex;
};

        二、访问限定符

        类是C++用来实现封装的方式,它把对象的属性和方法结合在一起,通过访问权限的选择,就可以把我们实现的方法提供给外部的用户使用。

      权限的选择就要通过访问限定符来实现了,访问限定符共分为三类:publicprotectedprivate,现在我们可以把protecte和private的功能看做相同(其中的不同会在以后的博客里解释),public看作另外一种。通过public修饰的成员可以在类位被直接访问,而private和protected修饰的成员则不能在类外被直接访问。访问权限的作用域从该访问限定符出现的位置开始直到下⼀个访问限定符出现时为⽌,如果后⾯没有访问限定符,作⽤域就到 }即类结束。同时访问限定符可以多次出现。

        三、类域

        类定义了一个新的作用域,类的所有成员都在类的作⽤域中,在类体外定义成员时,需要使⽤ :: 作⽤域操作符指明成员属于哪个类域。类域影响的是编译的查找规则,当不加作用域操作符时,编译器会默认把成员当成全部变量或者函数,编译时就会找不到,报错。指定类域以后,编译器就知道这个函数或者成员时指定类域里的成员变量或者函数,当前域找不到的时候就会到对应的类域中去查找。

        四、实例化

        ⽤类类型在物理内存中创建对象的过程,称为类实例化出对象。类是对象进⾏⼀种抽象描述,是⼀个模型⼀样的东西,没有分配空间,⽤类实例化出对象时,才会分配空间。⼀个类可以实例化出多个对象,实例化出的对象 占⽤实际的物理空间,存储类成员变量。类实例化出来的对象中只存储成员变量,同时成员变量也符合内存的对齐规则,详细的可以看我的另外一篇博客,http://t.csdnimg.cn/5QGaJ,这里有详细介绍是怎么计算内存大小的。类中的成员函数都存储在了一个单独的区域内,调⽤函数被编译成汇编指令[call 地址], 其实编译器在编译链接时,就要找到函数的地址。

        五、this指针

        当一个类实例化出了两个对象时,我们构造的类中也没有可以用来区别对象的东西,当使用对象调用成员函数的时候,编译器又是怎么区分是哪个对象调用的成员函数呢?这里用到的就是this指针。

        C++在编译器编译以后,会给类的成员函数默认在第一个位置增加一个当前类型的指针,比如我们这里的学生类,那增加的指针就是student* const this,通过这个指针,编译器就能区别到底是哪个对象在调用成员函数,同时类的成员函数中访问成员变量的本质也是通过this指针在访问。C++还规定不能在实参和形参的位置显⽰的写this指针(编译时编译器会处理),但是可以在函数体内显⽰使⽤this指针

        实践:

        this指针存在内存的哪个区域?

        A. 栈 B.堆 C.静态区 D.常量区 E.对象⾥⾯

        首先排除E选项,因为前面就说过了,对象中只存储成员变量,在计算大小时,我们也没有多计算一个指针的大小,所以E选项可以排除。C选项静态区是用来存放静态变量和全局变量的地方,显然也不是。D选项常量区是存放常量,而this是一个指针,显然也不是。B选项堆区,堆区存放的数据我们在学习malloc也了解到了,malloc出来数据是存放在堆区的,但是我们也没有为this指针申请内存空间,所以也不可能是放在堆区。所以this指针是存放在栈区里的。

        以下代码编译运行的结果是什么?

        A、编译报错 B、运⾏崩溃 C、正常运⾏

#include<iostream>
using namespace std;
class A
{
	public :
	void Print()
	{
		cout << "A::Print()" << endl;
		cout << _a << endl;
	}
private:
	int _a;
};
int main()
{
	A* p = nullptr;
	p->Print();
	return 0;
}

        有人看到这里类A的对象是一个指针p指向了空指针,然后这个空指针调用了函数就选了B选项,其实是不对。这里虽然对象p指向了空指针,也用空指针区调用成员函数了,但是前面我们也了解了,成员函数是被编译器编译成汇编指令[call 地址],所以在调用这个成员函数Print的时候,并没有对成员变量进行操作,也就是说没有对这个指针进行解引用操作,而空指针只有在你对它进行解引用时,才会运行崩溃,这里并没有,所以这个程序可以正常运行。但是如果在这个Print函数里对成员变量_a进行操作了,那就会发生运行崩溃了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值