外贸网站自建站,掏宝网网站建设评价表,稀奇古怪好玩有用的网站,网络营销相关的岗位有哪些目录
1.面向过程和面向对象初步认识
2.类的引入
3.类的定义
4.类的访问限定符及封装
4.1 访问限定符
4.2 封装
5.类的作用域
6.类的实例化
7.类的对象大小的计算
8.类成员函数的this指针 1.面向过程和面向对象初步认识
C语言是一门面向过程的语言#xff0c;注重的…目录
1.面向过程和面向对象初步认识
2.类的引入
3.类的定义
4.类的访问限定符及封装
4.1 访问限定符
4.2 封装
5.类的作用域
6.类的实例化
7.类的对象大小的计算
8.类成员函数的this指针 1.面向过程和面向对象初步认识
C语言是一门面向过程的语言注重的是解决问题的过程举个例子——洗衣服洗衣服的过程是拿衣服——放进洗衣机——放洗衣液——放水——打开洗衣机——开始工作——结束——晾衣服注重整个过程C是一门面向对象的语言注重的是解决问题时候涉及的对象比如洗衣服的时候涉及到了衣服洗衣机水洗衣液等对象注重的是对象交互来解决某个问题。 2.类的引入
在C语言中的结构体里面只能包含变量但是在C里面觉得结构体里面只能放变量不太方便于是规定函数也可以放在里面
struct St
{int a;int b;int c;int Add(int x,int y){return x y;}
};
int main()
{struct St s1;cout s1.Add(1, 2);return 0;
}
而在中C更喜欢使用class来定义类那么这样有有什么好处呢 比如我们写个栈的初始化C语言的写法是定义好之后创建函数传参传栈的指针进去再进行初始化C不用
class Stack
{void StackInit(){arr nullptr;size capacity 0;}int* arr;int size;int capacity;};
如此直接进行初始化就可以了。 3.类的定义
类的定义使用的关键字是class定义的时候和结构体一样花括号后面都有一个分号class后面跟的就是类名
class ClassName
{//...
};
其中类体(花括号)里面的变量叫做类的属性或者是成员变量类体里面的函数叫做类的方法或者成员函数。
类中定义函数的时候有两种方法一是定义和声明放在一起如:
class ClassName
{int Sub(int ,int ){return 1;}//...
};
二是声明和定义放在对应的文件里面如
//Stack.hclass Stack
{
public:void Print();private:int* arr;int size;int capacity;};
//Stack.cppvoid Stack::Print()
{cout Print endl;
}int main()
{Stack s1;s1.Print();return 0;
}这里有两个需要注意的地方一个是头文件里面的public和private一个是.cpp里面的函数定义。
当定义和声明分离的时候定义函数的时候要在函数名前面加上类名和两个冒号这是代表去这个类域里面访问这个函数。
定义变量的时候class Stack s1 和 Stack s1都是可以的那么方便起见我们就不写class反正有没有都是可以的。
一般建议的还是第二种声明和定义分开的形式这样代码可读性更大简洁度更高其次就是函数命名的一些建议
class Date
{
public: void Init(int year,int month,int minute){_year year;_month month;_minute minute;}
private:int _year;int _month;int _minute;
};命名类里面的变量的时候大多数情况下加一个下划线_这是因为如上情况的时候避免混淆初始化的时候如果变量也是year那么就是year year代码的可读性就非常差那有人说把参数的year换成y不就行了
实际上参数的命名最好要有比较明显的实际意义取名为y这谁知道参数对应的含义是什么呢 4.类的访问限定符及封装
4.1 访问限定符
上文还有一个注意事项没有介绍就是public和private的介绍这是C中定义类的访问限定符顾名思义就是访问变量的时候访问是否会受到限制。
那么这有什么意义呢
就好比文物展览如果没有保安没有文物警戒线等文物是不大能保存完整的这时候“访问限定符”就起作用了可以隔绝一部分没有素质的人。
代码也是如此C语言中结构体定义好之后就是谁都可以访问它所以比较考验程序员的素质C不一样C加了访问限定符有些变量就不能被随意访问就起到了一定的保护作用。
默认的是用private修饰也就是默认是私有的不让访问。
访问限定符一共有3个privatepublicprotected
关于访问限定符的说明 1 private和protected在外部不能直接被访问,public可以直接被访问
2 访问限定符的作用域是从该限定符开始一直到下一个限定符出现中的区域
3 class默认限定符为privatestruct默认限定符为public因为要兼容C语言
4.2 封装
面向对象有三大特性封装继承多态。
封装就是利用了访问限定符数据和使用数据的方法的结合达到隐藏对象的具体细节和属性但是可以通过接口的实现和外界进行交互。 封装其实就是管理让使用者使用该使用的不该使用的就是不使用比如电脑电脑的内部CPU,GPU怎么工作的我们是不用关心我们关心的是我们使用电脑可以完成什么样的工作这就是一种封装。 5.类的作用域
类定义好了之后就是单独创建了一个域这个域叫做类域和命名空间一样我们使用里面的成员的时候我们需要指定一下是哪个地方的比如
class calculator
{
public :int Add(int ,int);
};int calculator::Add(int x, int y)
{return x y;
}
int main()
{calculator c1;cout c1.Add(2,4) endl;return 0;
}
目前我们学了 局部域全局域命名空间域类域要注意区分。 6.类的实例化
类就是一个模型对象就是根据这个模型创建出来的所以类和对象常常放在一起类的实例化我们就可以理解为我们有一张设计图纸我们根据设计图纸创建了一些东西这个过程就叫做实例化。
只有实例化出来的对象才可以存放东西因为类是不能存放数据的图纸怎么存放数据是吧。
class calculator
{
public :int Add(int ,int);
private:int _a;
};int main()
{calculator _a 1;return 0;
}
如果直接给数据就会报错了。
那么提个问题
类里面的成员变量是声明还是定义
答案是声明也就是说在类里面告诉了你有这个东西但是我还没有给它开辟空间这也是实例化之前不能放数据的一个理由。
那么什么时候是定义呢
实例化的时候我们开辟了空间这个时候就是定义因为我们开辟了空间可以用来存放数据了。 7.类的对象大小的计算
我们来看下面五个类
class C1
{
public:int Add();
};
class C2
{
private:int _a;
};
class C3
{};
class C4
{char c;
};
class C5
{
public:int Add();char c;
};
试问三个类的大小是多大
第一个类有函数第二个类有一个int第三个类是空类。
问题在于函数算不算进去
因为类是结构体演化而来的所以计算的是套用结构体的内存对齐。 空类的内存是1这是因为空类里面没有东西为了存这个类的地址所以必须开辟一个字节用来保存它的地址但是不存储数据。
C2 和 C3对比就知道一个是4字节一个是1字节因为一个是int一个是char。
但是C1和C3对比都是一个字节但是函数的内存不可能是一字节所以C1实际上也是空类这里结合C5和C1也知道函数是不占内存空间的。
所以计算类的大小的时候函数不算进大小其次就是空类的大小是1这个1是用来存储类的地址的其余就是结构体的内存对齐了。 8.类成员函数的this指针
class Cl
{
public:int Add(int ,int);
private:int _a;char _c;
};
int Cl::Add(int x,int y)
{return x y;
}
int main()
{Cl c1;int ret1 c1.Add(1, 3);Cl c2;int ret2 c2.Add(2, 5);return 0;
}
先来看这样一段代码提问调用的函数是一个函数吗还是说调用的是不同对象中的函数
如果调用的是不同的函数也就是内存为函数开辟了两个函数栈帧那么汇编代码中的反汇编call对应的函数的地址应该是不同的那么
在汇编代码中对应的地址是一样的说明调用的函数是一个这也可以解释前面的为什么空类里面有一个函数的时候对应的大小却是1因为函数放在的区域是公共代码段所以计算大小的时候函数的大小不算在里面。
那么问题来了函数只有一个系统是怎么使用函数的一个函数怎么应用不同的参数呢
C编译器给每个“非静态的成员函数“增加了一个隐藏 的指针参数让该指针指向当前对象(函数运行时调用该函数的对象)在函数体中所有“成员变量” 的操作都是通过该指针去访问。只不过所有的操作对用户是透明的即用户不需要来传递编 译器自动完成。这个隐藏的指针参数就是this指针。
void Cl::Print(int x)
{cout x endl;
}
void Cl::Print(Cl* this,int x)
{cout this-x endl;
}
就像如此通过指针来实现各种操作也就达到了一个函数多个对象使用的目的。
但是this指针实现的时候都是透明的我们不需要手动参与编译器会自己实现。
下面来看两个关于this指针的题目
class A
{
public :void Print(){cout Print() endl;}
private:int _a;
};int main()
{A* p nullptr;p-Print();return 0;
}
class A
{
public :void Print(){cout _a endl;}
private:int _a;
};int main()
{A* p nullptr;p-Print();return 0;
}
问编译结果是否正常
第一个代码的编译结果是正常的虽然类指针是空指针但是访问的不是成员变量那么实际上的空指针就不会用上那么this指针是空指针是没问题的没用到空指针程序就不会崩溃。
第二个代码就会崩溃因为this指针接收了传过来的空指针我们又用到了这个空指针访问成员变量程序就会崩溃了。 void Print(){cout this endl;//cout _a endl;}
this指针打印出来就是空的。 感谢阅读