局域网建设网站,昆明酒店网站建设,广州外贸网站推广,it行业是什么工作 做什么的一#xff0c;类的定义
1.1类定义格式
class为定义类的关键字#xff0c;Stack为类的名字#xff0c;{}中为类的主体#xff0c;注意类定义结束时后面分号不能省略。类体中内容称为mian类的成员#xff1a;类中的变量称为类的属性或成员变量; 类中的函数称为类的方法或者…一类的定义
1.1类定义格式
class为定义类的关键字Stack为类的名字{}中为类的主体注意类定义结束时后面分号不能省略。类体中内容称为mian类的成员类中的变量称为类的属性或成员变量; 类中的函数称为类的方法或者成员函数。比如我们下面的一个简单的栈结构例子(不完整,作为引子使用)
using namespace std;class Stack
{
public:void Init(int n 4){int* tmp (int*)malloc(sizeof(int) * n);if (tmp nullptr){perror(realloc fail!);exit(EXIT_FAILURE);}_arr tmp;top 0;capacity n;}void Destory(){free(_arr);_arr nullptr;top capacity 0;}
private:int* _arr;int top;int capacity;
};int main()
{Stack d1;d1.Destory();return 0;
}
我们可以看到类的使用方法与我们C中所学习的结构体非常类似且class定义的类名可以直接代表类型不需要我们再去使用typedef而我们的C中strcut也升级为了类在struct中可以定义函数但我们一般还是在C中使用class定义类。
除此之外我们的类的成员函数前都默认加有我们的inline:
void Init(int n 4)//inline void Init(int n 4)
{int* tmp (int*)malloc(sizeof(int) * n);if (tmp nullptr){perror(realloc fail!);exit(EXIT_FAILURE);}_arr tmp;top 0;capacity n;
}
1.2访问限定符
我们注意到在上面的栈代码中有public与private这就是我们的类的访问限定符我们的类访问限定符一共有三种 1.public修饰的成员在类外可以直接被访问protected和private修饰的成员在类外不能直接被访问protected和private是⼀样的以后介绍到继承部分时才能体现出他们的区别。
2.访问权限作用域从该访问限定符出现的位置开始直到下⼀个访问限定符出现时为止如果后面没有访问限定符作用域就到 }即类结束。
3.class定义成员没有被访问限定符修饰时默认为privatestruct默认为public。
4.⼀般成员变量都会被限制为private/protected需要给别⼈使用的成员函数会放为public。
1.3类域
这部分其实与我们的namespace有些许类似类域影响的是编译的查找规则就比如说我们要直接使用上面代码中的Init函数如果不指定类域Stack那么编译器就把Init当成全局函数那么编译时找不到arr等成员的声明/定义在哪里就会报错。指定类域Stack就是知道Init是成员函数当前域找不到的arr等成员就会到类域中去查找。
class Stack
{
public:void Init(int n 4){int* tmp (int*)malloc(sizeof(int) * n);if (tmp nullptr){perror(realloc fail!);exit(EXIT_FAILURE);}_arr tmp;top 0;capacity n;}
private:int* _arr;int top;int capacity;
};int main()
{Stack::Init();//正确调用方法Init();//编译器找不到Init函数return 0;
}
二实例化 2.1实例化的概念
1.用类类型在物理内存中创建对象的过程称为类实例化出对象。
2.类是对象进行⼀种抽象描述是⼀个模型⼀样的东西限定了类有哪些成员变量这些成员变量只是声明没有分配空间用类实例化出对象时才会分配空间。
3.⼀个类可以实例化出多个对象实例化出的对象占用实际的物理空间存储类成员变量。所以简单来说我们的类就像盖房子的图纸一样对着图纸建造出我们的房子就是我们的实例化。
2.2对象大小
我们在上面说过类的定义中是有函数的成员变量的大小我们在C语言中就已经详细了解过了不多赘述。我们来看类的成员函数假如我们的成员函数也是占有空间的那我们去定义100个类是不是就要去至少实例化100个成员函数但我们知道在实际使用的时候拿我们上面的Stack来举例
class Stack
{
public:void Init(int n 4){int* tmp (int*)malloc(sizeof(int) * n);if (tmp nullptr){perror(realloc fail!);exit(EXIT_FAILURE);}_arr tmp;top 0;capacity n;}void Destory(){free(_arr);_arr nullptr;top capacity 0;}
private:int* _arr;int top;int capacity;
};int main()
{Stack d1;Stack d2;d1.Destory();d2.Destory();return 0;
}
可以看到两个相同的类用的是同一个函数这样不就造成了不必要的实例化了。其实函数被编译后是⼀段指令对象中没办法存储这些指令存储在⼀个单独的区域(代码段)那么对象中非要存储的话只能是成员函数的指针。同时函数指针是不需要存储的函数指针是⼀个地址调用函数被编译成汇编指令[call 地址] 其实编译器在编译链接时就要找到函数的地址不是在运行时找只有动态多态是在运行时找就需要存储函数地址这个我们以后的文章会介绍。 接下来我们来看几个例子
class A
{public :void Print(){cout _ch endl;}
private:char _ch;int _i;
};
class B
{public :void Print(){//...}
};
class C
{};
对于A我们可以轻松的算出其大小为8byte但是C和B呢。猛一看我们上面不是说过只有实例化的对象才会分配空间所以按照常理来说B和C均为0但是实际上为1为什么
B b1;
C c1;
如果为0那我们上面定义的两个b1和c1所分配的空间就是0如果⼀个字节都不给怎么表示对象存在过呢所以这里给1字节纯粹是为了占位标识对象存在。
三this指针 当我们定义了两个Stack对象时编译器是如何区分d1与d2呢。事实上编译器会在编译的时候自动在后面补上一个this指针
d1.Init(d1);
d2.Init(d2);void Init(int n 4)//实际调用后void Init(Stack const* this,int n 4)
{int* tmp (int*)malloc(sizeof(int) * n);if (tmp nullptr){perror(realloc fail!);exit(EXIT_FAILURE);}_arr tmp;top 0;capacity n;
}
所以类的成员函数中访问成员变量本质都是通过this指针访问的。除此之外C规定不能在实参和形参的位置显示的写this指针(编译时编译器会处理)但是可以在函数体内显示使用this指针。
下面让我们来看两个经典案例 乍一看两个都对空指针进行了解引用二者均会产生运行崩溃(切记编译错误为语法上的错误)但实际上只有第二种情况会报错。我们上面也说过成员函数的调用与我们定义的对象没有关系他们的使用实际是直接call使用的 所以在第一种情况下并没有发生对空指针的解引用但第二种则是需要成员变量去完成函数运转所以会发生对空指针的解引用进而导致编译报错。
四C中struct与class的区别