有哪些公司建设网站,做个ppt模板网站开发,网站建设pdf下载,wordpress 并发量C#xff1a;类与对象#xff08;上#xff09; 类的引入类的定义访问限定符类域实例化对象模型this指针 类的引入
C的类是基于C语言的结构体优化出来的#xff0c;那我们先来看一看C对结构体有哪些优化点。
C语言与C的结构体的类型名称略有区别#xff0c;我们看一个案… C类与对象上 类的引入类的定义访问限定符类域实例化对象模型this指针 类的引入
C的类是基于C语言的结构体优化出来的那我们先来看一看C对结构体有哪些优化点。
C语言与C的结构体的类型名称略有区别我们看一个案例
//C语言的结构体
struct ListNode1
{int val;struct ListNode1* next;
};//C的结构体
struct ListNode2
{int val;ListNode2* next;
};int main()
{struct ListNode1 L1;//C语言的结构体创建变量ListNode2 L2;//C的结构体创建变量
}一开始我们定义了两个结构体ListNode1和ListNode2在mian函数中我们分别对两个结构体创建了变量。 在C语言的结构体创建的变量时需要用struct ListNode1作为类型来创建。 而在C的结构体创建变量时只需要ListNode2作为类型来创建。
也就是说在C语言中结构体创建变量需要加上struct关键字而C中优化了可以无需这个关键字。
所以我们在结构体内部定义的next节点的指针也分别是struct ListNode1*和ListNode2*。
C语言中结构体只能用于定义变量但是在C中结构体内不仅可以定义变量还可以定义函数。
struct stack
{void Init(){cout 初始化栈 endl;}void Push(int x){cout x 被压栈了 endl;}void Destroy(){cout 销毁栈 endl;}int stackSize(){return size;}int* a;int size;int capacity;
};上述代码中我们定义了一个stack结构体其内部有asizecapacity三个基本变量这是在C语言结构体范围内的。但是我们还额外定义了几个函数在其内部InitPushDestroy以及stackSize。我们可以通过结构体来调用某一个函数。
那么要如何调用函数 其实只要把函数当作一个普通的变量用.操作符访问即可。 这样我们就正常访问到了结构体内部的函数。
我们看到结构体内的一个函数
int stackSize()
{return size;
}这个函数里面没有size这个形参为什么可以直接使用size? 在同一个结构体内部的变量是可以直接被结构体内的函数访问到的。因为size存在于结构体中所以结构体内的函数可以访问到size。
但是为了更好的区别C语言的结构体与C的结构体C更喜欢用一种叫做类的结构来替代结构体。 类的定义
class关键字是定义类的关键字在C中直接使用class代替struct即可而我上方说的所有C对结构体的优化在类中也使用。
上述结构体可以定义为以下的类
class stack
{void Init(){cout 初始化栈 endl;}void Push(int x){cout x 被压栈了 endl;}void Destroy(){cout 销毁栈 endl;}int stackSize(){return size;}int* a;int size;int capacity;
};其中函数部分叫做成员函数或者方法变量部分叫做类的属性或者成员变量。
但是这样定义类会有一个问题 为什么我们定义的类无法访问到其内部的函数了
这是因为对于类来说其所有成员会被分为公有和私有接下来我们看看什么是公有私有以及如何转换 访问限定符 public修饰的成员在类外可以直接被访问protected和private修饰的成员在类外不能直接被访问(这方面protected和private是类似的)访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止如果后面没有访问限定符作用域就到} 即类结束。class的默认访问权限为privatestruct为public(因为struct要兼容C语言) 首先看到第12点 public修饰的成员在类外部可以直接访问而 protected和private修饰的成员在类外不能直接被访问。 再看到第五点 class的默认访问权限为privatestruct为public。
也就是说class定义的类默认外部无法访问到其内部的成员所以当我们把struct转为 class外部访问函数就报错了。
所以以上代码要改为
class stack
{
public:void Init(){cout 初始化栈 endl;}void Push(int x){cout x 被压栈了 endl;}void Destroy(){cout 销毁栈 endl;}int stackSize(){return size;}int* a;int size;int capacity;
};这样整个类都可以被外部访问了因为所有的成员都在public下方。 但是我们很多时候不希望别人修改我们的数据只希望别人调用函数。
所以我们可以把成员变量改为私有
class stack
{
public:void Init(){cout 初始化栈 endl;}void Push(int x){cout x 被压栈了 endl;}void Destroy(){cout 销毁栈 endl;}int stackSize(){return size;}
private:int* a;int size;int capacity;
};对于protect这里不做详解其与private的区别要在后续才能体现。 类域
类是单独享有一个域的所以类与类之间可以有同名函数与变量如下
class stack
{
public:void Init(){cout 初始化栈 endl;}void Push(int x){cout x 被压栈了 endl;}void Destroy(){cout 销毁栈 endl;}int stackSize(){return size;}
private:int* a;int size;int capacity;
};class List
{
public:void Init(){cout 初始化顺序表 endl;}void Push(int x){cout x 顺序表尾插 endl;}void Destroy(){cout 销毁顺序表 endl;}private:int* a;int size;
};以上代码中定义了一个顺序表List一个栈stack两者都有InitPushDestroyasize。但是两者并不冲突因为在不同的类域中。 实例化
类是对对象进行描述的是一个模型一样的东西限定了类有哪些成员定义出一个类并没有分配实际的内存空间来存储它。
可以理解为类就是一个建筑图纸其规定了一个建筑有哪些房间房间大小尺寸等等。但是图纸是不可以住人的也就是说还不是一个可以使用的屋子此时就需要实例化根据图纸把屋子建出来。 比如我们上述的栈的类将其实例化就是
int main()
{stack s1;stack s2;stack s3;stack s4;return 0;
}这里我们进行了四次实例化s1s2s3s4是四个不同的实例不过我们一般将其称为对象。这四个对象就相当于根据图纸造出来的屋子它们的结构完全一致只是可能经过使用后数据会不同。可以理解为不同装修方式会对房屋的内部造成不同的影响但是房屋的结构依然是一致的。 对象模型
我们先尝试检测一个对象的大小
class stack
{
public:void Init(){cout 初始化栈 endl;}void Push(int x){cout x 被压栈了 endl;}void Destroy(){cout 销毁栈 endl;}int stackSize(){return size;}
private:int* a;int size;int capacity;
};int main()
{cout sizeof(stack) endl;//输出16return 0;
}如果你结构体的位段学的好的话你会发现其实结构体中只有asizecapacity三个成员大小也是16个字节。 也就是说类中的函数没有占用类的空间。
其机制为类的成员变量放在对象本身的空间中而函数会被放在一个公共代码段因为函数是一致的。 所以计算类的大小时只需要通过结构体的位段计算成员变量的大小。
除此之外如果一个类是空类或者只有成员函数那么编译器依然会为其分配一个字节的空间。 this指针
讲清楚了对象模型后我们来想一个问题既然大家都是用的同一个函数那么这个被调用的函数怎么知道是谁调用的
比如这样
class myclass
{
public:void Init(int x, int y, int z){_x x;_y y;_z z;}void Add(){cout _x _y _z endl;}private:int _x;int _y;int _z;
};int main()
{myclass c1;myclass c2;c1.Init(1, 2, 3);c2.Init(4, 5, 6);c1.Add();c2.Add();return 0;
}创建了两个myclass类的对象c1和c2c1初始化三个成员为123c2初始化三个成员为456。 调用Add函数时对于Add函数来说它是如何知道要完成123还是456?
这就涉及到了this指针。 C编译器给每个“非静态的成员函数“增加了一个隐藏的指针参数让该指针指向当前对象(函数运行时调用该函数的对象)在函数体中所有“成员变量”的操作都是通过该指针去访问。只不过所有的操作对用户是透明的即用户不需要来传递编译器自动完成。
也就是说我们在调用类的函数时函数会偷偷传递一个参数this指针它指向了成员的地址这样就可以知道是谁调用了这个函数。
this指针有以下特性
this指针被const修饰了函数内部是不允许修改this指针的指向的。this指针在函数内部是允许使用的
比如我们可以在类中添加一个函数
void tellMeThis()
{cout this endl;
}这个函数会输出一个隐藏的变量this我们可以访问this指针。
但是如果我们想在函数内部修改this
void changeThis()
{this NULL;
}这就是非法的了。