北京网站制作公司报价,合肥网络优化公司有几家,搜索引擎优化怎么做,重庆做网站外包公司10.2.2 C中的类 类是一种将抽象转换未用户定义类型的C工具#xff0c;它将数据表示和操作数据的方法合成一个整洁的包。
接口#xff1a;一个共享框架#xff0c;供两个系统交互时使用。
1.访问控制
使用类对象的程序可以直接访问类的公有部分#xff0c;但只能通过公有…10.2.2 C中的类 类是一种将抽象转换未用户定义类型的C工具它将数据表示和操作数据的方法合成一个整洁的包。
接口一个共享框架供两个系统交互时使用。
1.访问控制
使用类对象的程序可以直接访问类的公有部分但只能通过公有成员函数访问对象的私有成员
防止程序直接访问数据被称为数据隐藏。
数据隐藏不仅可以防止直接访问数据而且还让开发者无需了解数据是如何被表示的。
将实现细节放在一起并将它们与抽象分开称为封装
2.private和public
在类中使用private来强调成员是私有的public强调成员是公有的。
在class声明的类中成员默认是私有的而在struct中成员默认是公有的。
10.2.3实现类的成员函数
定义成员函数时使用作用域解析运算符来来标识函数所属的类
类方法可以访问类的private组件
如stock是一个类名它有一个叫fun的成员函数
void stock::fun
{
。。。。
}
1.内联函数
定义在类声明中的函数都将自动成为内联函数类声明常将短小的成员函数作为内联函数如果想在类外声明内联函数可以使用inline关键字。
内联函数要求每个使用它们的文件中都对其进行定义为了方便使用内联函数我们将内联函数放在类的头文件中。
2.方法使用哪个对象
创建对象 类名 对象名类名相当于一种数据类型 对象名是变量
使用成员函数方法 对象名.函数名参数
10.3类的构造函数和析构函数
对象的变量不能像初始化int变量 那样来进行初始化因为对象的存在私有成员在类外无法进行访问。而类的成员函数可以访问这些成员变量因此我们可以使用类的成员函数对对象进行初始化而类的构造函数就是C用来初始化对象的一个函数。
构造函数在创建对象的时候会被自动调用。
构造函数
名字必须与类名一致且没有返回类型可以有参数可以重载也就是可以有多个构造函数。如fun类的构造函数为 fun;
若不定义构造函数程序将提供一个默认的隐藏的构造函数而这个构造函数并不进行任何操作。若手动定义了多个构造函数
程序则会根据定义对象时候括号里的参数来确定使用哪一个构造函数。
如果提供了非默认的构造函数下列语句会出错
fun A定义一个fun类的对象A
有两种方法可以解决这个问题一是在类里加入一个默认的构造函数二是给非默认的构造函数提供默认参数。
但是这两种方法不能同时用如果同时用的话fun A可以使用任意一个构造函数于是程序将不知道使用哪一个会爆错。 列表初始化
听名字就是列一个表进行初始化
语法就是下面这种 #include iostream using namespace std; class A { int w; public: A(int j0):w(j){} }; int main() { A a; return 0; }
在函数名后加一个分号然后写出变量名 变量名后跟一个括号意思是用括号里这个值来初始化这个变量
注意事项
这种格式只能用于构造函数必须用这种格式来初始化非静态const数据成员和引用数据成员
什么时候初始化列表是必用的呢
1. 类成员为const类型
2. 类成员为引用类型 #include iostream using namespace std; class A { public: A(int v) : i(v), p(v), j(v) {} void print_val() { cout hello: i j endl;} private: const int i; int p; int j; }; int main() { int pp 45; A b(pp); b.print_val(); } 构造函数 所说是起到初始化的作用但是实际上是通过赋值的操作来进行初始化的但是const变量 和引用无法通过赋值来进行初始化所以要用初始化列表。 3. 类成员为没有默认构造函数的类类型 #include iostream using namespace std; class Base { public: Base(int a) : val(a) {} private: int val; }; class A { public: A(int v) : p(v),b(v) {} void print_val() { cout hello: p endl;} private: int p; Base b; }; int main() { int pp 45; A b(pp); b.print_val(); } 原因同样是创建对象时要初始类成员的每一个成员
(如果没有在初始化列表里面编译器会自动使用它的默认的构造函数进行初始化但是它没有默认构造函数所以会编译报错所以没有默认构造函数的成员变量需要使用初始化列表进行初始化)
这里如果把初始化列表里的b删掉就会爆错同理类存在继承关系派生类必须在初始化列表里初始化。
4. 如果类存在继承关系派生类必须在其初始化列表中调用基类的构造函数 PS若一个类中有其他类的对象那么该如何初始化这个类呢
只需在类的构造函数的初始化列表里加上其他类对象的名字及其参数列表即可。
派生类构造函数的执行顺序
① 调用基类构造函数初始化基类数据成员
② 调用子对象构造函数初始化子对象数据成员
③ 执行派生类自身的构造函数初始化自己新增数据成员。 析构函数
析构函数的特点
一个类只有一个析构函数不能重载名字与类名相同定义时候要加上~没有参数不能有返回值没有返回值类型
对应于构造函数初始化对象析构函数是用来释放对象的内存的可以将delete等操作放在析构函数里析构函数在对象离开其作用域的时候自动执行。
对象析构的顺序和创建的顺序相反即先构造的后析构后构造的先析构
但这并非绝对成立
在不同的作用域中的对象或者具有不同存储类别的对象调用构造函数和析构函数的顺序也会有所不同
一个程序中有多个文件。在多个文件中定义了全局对象,那么这些对象的执行顺序是不确定的在函数中定义局部自动对象如果函数被多次调用多次调用构造函数和析构函数如果函数中定义静态局部对象那么函数调用结束时对象并不释放只有main结束或调用exit时才调用析构函数。 什么时候调用析构函数
如果在函数中定义了一个对象当函数调用结束时释放对象前自动执行析构函数static 局部对象在函数调用结束时包含的对象不会被释放只在main函数结束或调用exit函数时才调用static局部对象的析构函数。如果定义了一个全局对象则在程序的流程离开其作用域时如main函数结束或exit语句调用该全局对象的析构函数如果用new运算符动态地建立了一个对象当用delete 运算符释放对象时先调用该全局对象的析构函数。
10.4this指针
众所周知同一个类的多个对象公用一套方法那么在调用同一套方法的时候程序是如何知道要访问哪个对象里的成员的呢答案是通过this指针类的成员函数里有一个隐藏的指向对象的参数就是this指针。
具体看下面这个例子 #include iostream using namespace std; class Base { public: Base(int a) : val(a) {} void display(); private: int val; }; void Base::display() { coutvalendl;//实际上就是coutthis-valendl; } int main() { Base a(1),b(2); a.display();//看上去没有传参数实际上传了a的地址 } 10.5对象数组
对象数组跟结构体差不多这里就讲讲一些不同点。
首先是初始化由于对象有构造函数所以我们在初始化对象数组的时候要用大括号括起来将构造函数列出来来进行初始化
例如 const int max4; fun a[max]{ fun(1),fun(2),fun(3),fun(5)} 如果类只有一个成员变量则可以直接像数组那样赋值 如fun b[max]{1,2,3,4};
10.6对象指针
什么是对象指针
创建一个类的对象时系统会为每一个对象分配一定的存储空间以存放成员。对象空间的起始地址就是对象的指针。可以定义一个指针用来存放对象的指针。
语法 time *pt time t; ptt1; // 指针指向对象
对象指针的使用与普通指针使用差不多具体可以自行百度指针的使用