当前位置: 首页 > news >正文

坂田做网站建设好的网络公司泰州做兼职的网站

坂田做网站建设好的网络公司,泰州做兼职的网站,沈阳城市建设学院官方网站,网站建设可用性目录#xff1a;前言一、基础引入1.类的定义2.类的权限3.类的封装4.类的实例化5.计算类对象的大小结构体内存对齐规则空类的大小二、this指针this引入this指针的特性经典例题三、类的六个默认成员函数1、构造 析构构造函数析构函数2、拷贝 赋值拷贝构造… 目录前言一、基础引入1.类的定义2.类的权限3.类的封装4.类的实例化5.计算类对象的大小结构体内存对齐规则空类的大小二、this指针this引入this指针的特性经典例题三、类的六个默认成员函数1、构造 析构构造函数析构函数2、拷贝 赋值拷贝构造函数赋值运算符重载运算符重载注意赋值前置 后置流插入 流提取3、取地址 const取地址补充const成员总结前言 打怪升级第36天C语言是面向过程的语言c是面向对象的语言那么什么是面向过程和面向对象呢 下面我们以点外卖为例 一、基础引入 C语言中有自定义类型结构体我们可以在结构体中定义各种变量但是不能定义函数在c中我们为了将函数一起封装到对象内将struct的功能进行了扩展比如 struct Date {void Print(){cout _year / _month / _day endl;}int _year;int _month;int _day; };在c中更喜欢用 class 代替 struct如下 class Date {void Print(){cout _year / _month / _day endl;}int _year;int _month;int _day; };1.类的定义 class className {};class类的关键字 className类的名字我们可以自行设置 大括号内为类的成员可以有变量也可以有函数 注意结尾的分号不可少 类中的变量称为类的属性或成员变量类中的函数称为类的方法或者成员函数。 类的定义分两种 1.声明和定义都放在类内 注意函数在类内声明可能会被编译器当做内联函数。 class Date {void Print(){cout _year / _month / _day endl;}int _year;int _month;int _day; };2.声明和定义分离 注意函数名前需要在加上“ className ”注明作用域。 // Date.h class Date {void Print();int _year;int _month;int _day; };// Date.cpp #includedate.h void Date::Print() {cout _year / _month / _day endl; }一般更推荐第二种但是我们下方为了方便起见使用第一种方式。 2.类的权限 示例 #includeiostream using namespace std;struct Date1 {void Print(){cout _year / _month / _day endl;}int _year;int _month;int _day; };class Date2 // 和Date1“完全相同” {void Print(){cout _year / _month / _day endl;}int _year;int _month;int _day; };void Test02() {//struct Date1 d1; // 在C语言中我们在声明结构体变量时必须写上 structDate1 d1; // c中则允许省略因此两种写法都对d1._year 2023;d1._month 2;d1._day 5;d1.Print();Date2 d2;d2._year 2023; }这里就涉及到权限的问题了 类的权限 c实现封装的方式将类的变量和函数封装到一起通过访问权限的限制选择性的将其接口函数提供给使用者。 访问限定符说明 public修饰的成员在类外也可以被访问protected和private修饰的成员在类外不能直接被访问这里两者功能相似访问限定符的作用域从设置处开始到下一个限定符为止如果下方没有其他限定符作用域就到}既类结束class默认限定符为privatestruct为了兼容c默认限定符为public。 这里我们我就可以理解为何上面的访问情况会失败啦那么若想要成功访问我们该如何设置呢这里希望大家结合上面所讲权限的概念自行测试。 3.类的封装 面向对象分为三大特点封装、继承和多态。 在类和对象阶段我们主要探究类的封装特性那么什么是封装呢 封装将数据和操作数据的方法进行有机结合隐藏对象的属性和实现细节仅对外提供接口来和对象进行交互。 封装本质上是对对象进行管理好方便用户的使用。比如对于电脑这样一个复杂的设备提供给用户的就只有开关机键、通过键盘输入显示器USB插孔等让用户和计算机进行交互完成日常事务。但实际上电脑真正工作的却是CPU、显卡、内存等一些硬件元件。 对于计算机使用者而言不用关心内部核心部件比如主板上线路是如何布局的CPU内部是如何设计的等用户只需要知道怎么开机、怎么通过键盘和鼠标与计算机进行交互即可。因此计算机厂商在出厂时在外部套上壳子将内部实现细节隐藏起来仅仅对外提供开关机、鼠标以及键盘插孔等让用户可以与计算机进行交互即可。 在C语言中实现封装可以通过类将数据以及操作数据的方法进行有机结合通过访问权限来隐藏对象内部实现细节控制哪些方法可以在类外部直接被使用。 4.类的实例化 class Date { public:void Print(){cout _year / _month / _day endl;}private:int _year;int _month;int _day; };如上所示我们定义了一个名为Date的类那么此时这个类占用空间了吗 – – 如果无法确定我们来想一想int、float、double这些类型关键字在使用之前有占用空间吗答案肯定是没有的 那他们在什么时候占用空间呢答案是 任何时候都不会占用空间使用它们声明变量时编译器会给变量分配内存空间但是int、Date它们是不分配空间的它们就像一张盖房子的图纸我们按照图纸建造的房子会占用空间但是图纸是不会占用物理空间的。 class Date { public:void Init(int year){year year;}private:int year;int month;int day; }; 因此我们平时描述类成员变量时会将其特殊化如下 class Date { public:void Init(int year, int month, int day){_year year;}private:int _year; // 这样可以int _month;int _day;//int year_; // 这样也可//int month_;//int day_;//int mDay; // 这样也可这里全凭大家的喜好可以加以区分即可。//int mYear;//int mMonth; };5.计算类对象的大小 在类里面我们会有变量也会有函数那么我们该如何计算类对象的大小呢 这里有三种方法 一个类的大小是成员变量所占空间和成员函数所占空间的和 这种形式下每个类对象都有自己独立的变量和函数但是我们知道函数是可以共用的 那么我们就不需要这样每个类对象都拷贝一份成员函数这样会造成大量的空间浪费我们将它单独存储起来大家都调用同一份函数即可但是变量则不行每个对象的成员变量必须单独存储因此就进行了下方的优化。 成员变量加上指向成员函数的指针 只计算成员变量成员函数存放到公共代码段。 那么c到底采用的哪一种呢我们来验证一番 由此我们知道类的大小就是成员变量的大小总和成员函数会存放到公共代码段不会影响类的大小。 结构体内存对齐规则 第一个成员在与结构体偏移量为0的地址处。其他成员变量要对齐到某个数字对齐数的整数倍的地址处。 注意对齐数 编译器默认的一个对齐数 与 该成员大小的较小值。 VS中默认的对齐数为8结构体总大小为最大对齐数所有变量类型最大者与默认对齐参数取最小的整数倍。如果嵌套了结构体的情况嵌套的结构体对齐到自己的最大对齐数的整数倍处结构体的整 体大小就是所有最大对齐数含嵌套结构体的对齐数的整数倍。 空类的大小 class Test { public:void Print(){}};class Person {};void Test03() {cout Test size sizeof(Test) endl;cout Person size sizeof(Person) endl; }由于成员函数会存放到代码段因此有无成员函数对类对象的大小没有影响那么我们怎么得到了两个1呢 上面我们讲使用类实例化对象是需要开辟空间的而空类没有成员函数并不占用空间但是我们还需要表明我们实例化出了一个对象所以这个1字节的空间内并不存储数据只是为了占位表明我们实例化出了一个对象。 二、this指针 this引入 我们先来定义一个类 class Date { public:void Init(int year, int month, int day){_year year;_month month;_day day;}void Print(){cout _year / _month / _day endl;}private:int _year;int _month;int _day; };void Test01() {Date d1;d1.Init(2023, 2, 5);d1.Print();Date d2;d2.Init(2025, 1, 1);d2.Print(); }其实是我们c的祖师爷认为每次调用成员函数都需要传指针实在太麻烦指针使用不方便而且稍不留神就会出错所以就让编译器自己去获取对象的地址自己进行传参和操作 C中通过引入this指针解决该问题即C编译器给每个“非静态的成员函数“增加了一个隐藏的指针参数让该指针指向当前对象(函数运行时调用该函数的对象)在函数体中所有“成员变量”的操作都是通过该指针去访问。只不过所有的操作对用户是透明的即用户不需要来传递编译器自动完成。 this指针的特性 this指针的类型为 类名 * const 因此我们无法改变this指针的内容this指针只能在成员函数内部使用因为调用成员函数时才会自动传参this指针本质上是成员函数的形参当对象调用成员函数时将对象的地址作为实参传递给this形参所以对象中不存储this指针this指针是成员函数第一个隐含的指针形参一般由编译器通过ecx寄存器自动传递不需要用户进行传递。 我们在成员函数中使用成员变量时可以直接使用this指针不过在熟练掌握之后更推荐省略不写。 补充 class Person { public:void Init(int val){val val; // 我们之前讲如果成员变量和形参命名相同我们就无法完成对成员变量的赋值。}private:int val; };// 现在我们做以下修改 class Person { public:void Init(int val){this-val val; // 显式使用this指针后编译器就可以区分成员变量和形参当然我们还是更推荐使用不同的变量名}private:int val; }; 经典例题 提示总计三道例题每题的代码下方就是答案想要进行思考的朋友看过了代码后不要着急往下翻哦。 // 1.下面程序编译运行结果是 A、编译报错 B、运行崩溃 C、正常运行 class Person { public:void Init(int val){_val val;}void Print(){cout this endl;cout Person::Print endl;}private:int _val; };void Test02() {Person* pd;pd-Print(); }失败原因pd指针未进行初始化发生野指针访问。 // 2.下面程序编译运行结果是 A、编译报错 B、运行崩溃 C、正常运行 class Person { public:void Init(int val){_val val;}void Print(){cout this endl;cout Person::Print endl;}private:int _val; };void Test02() {Person* pd nullptr;pd-Print(); }这里我们就会有疑问了pd是一个空指针哎我们访问成员函数不应该使用类对象吗 我们话转上文“类的成员函数存放在公共代码段。” 也就是说成员函数并不在对象里我们访问成员函数不需要实例化出对象 那么我们在使用空指针调用成员函数是在代码段中进行查找找得到也就可以编译链接成功。 // 3.下面程序编译运行结果是 A、编译报错 B、运行崩溃 C、正常运行 class Person { public:void Init(int val){_val val;}void Print(){cout this endl;cout Person::Print endl;}private:int _val; };void Test02() {Person* pd nullptr;pd-Init(2023); } 这个和前一个的唯一区别就是调用的函数不同但是为何结果也不相同了 编译成功我们上面讲过成员函数存在于代码段我们使用空指针也可以访问成员函数 那么为何程序会崩溃 我们看一下Init函数的操作给成员变量赋值 那成员变量放在哪儿 – 在对象里我们访问成员变量是需要实例化出来对象的 那么我们就可以理解程序崩溃的原因了这里访问成员变量发生了空指针的解引用。 C中通过类可以将数据 以及 操作数据的方法进行完美结合通过访问权限可以控制那些方法在 类外可以被调用即封装在使用时就像使用自己的成员一样更符合人类对一件事物的认知。 而且每个方法不需要传递对象指针编译器编译之后该参数会自动还原。 三、类的六个默认成员函数 下面我们将来见识一下类中的 六位“天选之子” – 六个默认成员函数。 所谓默认成员函数就是当程序员自己不写的话编译器就自动帮他写 也就是说任何一个类里面都必须有对应的这六个函数即使是一个空类没有添加任何东西也不例外 其中前四个非常重要后两个我们了解即可。 1、构造 析构 构造函数 我们以前使用栈和队列的时候每次开始都需要进行初始化并且在使用结束时需要释放空间防止内存泄漏。 如下示例 typedef int STDataType; class Stack { public: // 初始化栈 void Init() {_a (STDataType*)malloc(sizeof(STDataType) * 4);_top 0;_capacity 4;cout 初始化成功. endl; }// ...// 销毁栈 void Destroy() {free(_a);_a NULL;_top _capacity 0;cout 栈销毁成功. endl; }private:STDataType* _a;int _top; // 栈顶int _capacity; // 容量 };int main() {Stack s;s.Init();// ...s.Destroy();return 0; }运行实例 初始化还好说如果不初始化程序会报错但是销毁的操作很多时候都会被遗忘而且此时编译器也不会有任何反应 因此很多时候会被大家忽略掉但是在做大型项目的时候一个程序需要跑一个月甚至更久刚开始不会有什么影响 可是随着时间的推移内存泄漏的问题会越来越严重主机的内存越来越小直至崩溃而且这种情况下并不容易发现问题。 而我们c的祖师爷也“受够了”这种情况想到既然每次都需要进行初始化和销毁那干脆就像this指针一样将把这个工作交给编译器来做这样不仅使用起来更方便还可以杜绝忘记调用的问题 因此就有了我们的构造和析构函数。 构造函数是特殊的成员函数值得注意的是构造函数虽然名字是构造但是并不是开辟空间创造对象而是初始化对象。 特征如下 函数名和类名相同没有返回值对象实例化出来时编译器自动调用构造函数只会调用一次可以进行重载 示例 class Person { public:Person(){_year 2023;_month 3;_day 5;}void Print(){cout _year / _month / _day endl;}private:int _year;int _month;int _day; };int main() {Person p;p.Print();return 0; }运行实例 上面所写的构造函数是无参构造函数我们也称其为默认构造函数 我们也可以使用缺省参数 // 添加默认缺省参数Person(int year 2023, int month 3, int day 5){_year year;_month month;_day day;}// 下面问大家一个问题下方构造函数写法正确吗如果有错误请问错在哪里。 // 大家可以想一想之后再往下解密答案欧~ class Person { public:Person(){_year 2023;_month 3;_day 5;}Person(int year 2023, int month 3, int day 5){_year year;_month month;_day day;}void Print(){cout _year / _month / _day endl;}private:int _year;int _month;int _day; };int main() {Person p;p.Print();return 0; }运行结果 由此我们一般只写全缺省的构造函数因为全缺省函数也包含了无参构造。 如果类中没有显示定义构造函数编译器会自动生成一个无参的默认构造函数如果类中定义了编译器将不再定义。 注意用户定义了任何一个构造函数编译器都不会再自动生成。 class Person { public:Person(int year, int month 3, int day 5) {_year year;_month month;_day day;}void Print(){cout _year / _month / _day endl;}private:int _year;int _month;int _day; };int main() {Person p;p.Print();return 0; }结果 编译器自动生成无参的默认构造函数。 这里有同学就会有疑问了既然我们不写编译器就会自动生成对应的默认构造函数那我们还需要“多此一举”自行实现吗 下面我们来看一下编译器自行实现的构造函数到底有什么作用吧。 上面讲到对于自定义类型会自动调用它的构造函数那么我们就来验证一下 typedef int STDataType; class Stack { public:// 初始化栈 Stack(int s 4){_a (STDataType*)calloc(s, sizeof(STDataType));_top 0;_capacity s;cout 初始化成功. endl;}// ...// 销毁栈 ~Stack(){free(_a);_a NULL;_top _capacity 0;cout 栈销毁成功. endl;}private:STDataType* _a;int _top; // 栈顶int _capacity; // 容量 };class PPP {private:Stack spush;Stack spop; };void Test01() {PPP p;// ...}补充上面我们说了析构函数对于内置函数类型不进行操作这个本身就是不合理的因此在c11中对它进行了一些补充 内置类型成员变量在类中声明时可以给默认值注意这里是缺省值而不是初始化或者赋值思考一下为什么 无参的构造函数和全缺省的构造函数都可以称为默认构造函数并且默认构造函数只能存在一个。 无参构造函数全缺省的构造函数以及编译器自动实现的构造函数都可以叫默认构造函数不需要传参数的构造函数。 析构函数 下面我们来了解一下析构函数析构函数是和构造函数配套使用的一个初始化一个销毁当然这个销毁并不是指对对象本身的销毁 局部对象的销毁是由编译器来做的。而对象在销毁时会自动调用析构函数完成对象中资源的清理工作。 函数名为 ~类名无参数无返回值在对象销毁时自动调用一个类只能有一个析构函数如果程序员不写编译器会自行实现析构函数无重载 编译器自行生成的析构函数对内置类型成员变量不做处理对于自定义类型成员变量会调用它的析构函数。和构造函数一模一样滴 如果类中没有资源申请是可以直接使用编译器自动生成的析构函数如Date类 有资源申请时一定要写否则会造成内存泄漏如Stack类。 2、拷贝 赋值 拷贝构造函数 拷贝拷贝顾名思义就是把一个变量再复制一份我们这里说的拷贝是指使用一个对象初始化一个新的对象 新的对象就是另一个对象的“拷贝”。 拷贝构造函数是构造函数的一个重载参数只有一个就是相同类型的对象这里有坑 下面我们来模拟实现一下 拷贝构造函数 拷贝构造是构造函数的一个重载形式拷贝构造的参数只能是同类型对象的引用采用值传递编译器直接报错会发生无穷递归调用。如果我们不写编译器会默认生成拷贝构造函数但是要注意编译器自行提供的拷贝构造是按字节进行拷贝的我们称之为浅拷贝或者值拷贝。 下面我们来见识一下 class Date { public:Date(int year 2023, int month 3, int day 5){_year year;_month month;_day day;}void Print(){cout _year 年 _month 月 _day 日 endl;}private:int _year 2023;int _month 3;int _day 6;; }; void Test02() {Date d1;Date d2(d1);Date d3 d1; // 这样写也是拷贝构造d1.Print();d2.Print();d3.Print(); }可见我们这里使用编译器自行提供的拷贝构造函数是没有问题滴 那么下面我们肯定就要来看一个有问题的代码啦 typedef int STDataType; class Stack { public:// 初始化栈 Stack(int s 4){_a (STDataType*)calloc(s, sizeof(STDataType));_top 0;_capacity s;cout 初始化成功. endl;}// ...// 销毁栈 ~Stack(){free(_a);_a NULL;_top _capacity 0;cout 栈销毁成功. endl;}private:STDataType* _a;int _top; // 栈顶int _capacity; // 容量 };void Test01() {Stack s1;Stack s2(s1);}欧~这里又是怎么一回事儿呢 让我们根据浅拷贝的定义来画图理解 由此可见当我们的类中有资源申请的时候就需要程序员自己来写拷贝构造函数来防止浅拷贝问题值拷贝而程序员自我实现的拷贝构造函数我们称为深拷贝。 在编译器自动生成的默认拷贝构造函数中对于内置类型变量会进行值拷贝对于自定义类型变量会调用它的拷贝构造函数。拷贝构造函数调用场景 ①使用类对象创建新对象 ②类对象作为函数参数 ③类对象作为函数返回值 注如果采用传引用传参或者引用返回就不需要调用拷贝构造因为实际传的是指针但是 并不是所以情况都可以传引用例如要返回的是局部变量。 赋值运算符重载 下面在介绍赋值成员函数之前我们先来了解一下c中十分十分十分重要的一个知识运算符重载 运算符重载 c为了增强代码的可读性引入了运算符重载运算符重载是具有特殊函数名的函数它也具有返回值、函数名以及参数列表 其返回值和参数列表和普通函数类型。 关键字operator功能赋予运算符新的功能函数名 operator后跟需要重载的运算符用法返回值 operator运算符 参数 示例重载赋值运算符 class Date { public:Date(int year 2023, int month 3, int day 5){_year year;_month month;_day day;}// void operator(Date d) // 这里可以采用值传递吗// 可以因为采用值传递的话会多走一步拷贝构造和赋值没有关系。void operator(const Date d) // 推荐使用引用因为走一步拷贝构造完全没必要 也推荐加const防止因为疏忽把d的值给改了{_year d._year;_month d._month;_day d._day;}void Print(){cout _year 年 _month 月 _day 日 endl;}private:int _year 2023;int _month 3;int _day 6;; }; void Test02() {Date d1;Date d2(d1);Date d3 d1; // 这样写也是拷贝构造Date d4;d4 d1; // 这样写是赋值d1.Print();d2.Print();d3.Print();d4.Print(); }好的那下面我们就又有新的疑问了为什么需要重载赋值操作符编译器都已经帮我们写好了我们是不是就没有必要再来了解了 答案嘛肯定是否定的 因为编译器给我们提供的重载赋值操作符只是简单的值拷贝并不能满足用户的需求 并且编译器只提供了一个重载赋值操作符如果我们想要比较一下两个日期的大小计算一下两个日期之间有多少天简单地使用 大于、小于号或者减号是不对的因为编译器并不知道我们到底是想要只比较年份还是只比较月份等等 因此这些都需要程序员自行实现告诉编译器应当如何做。 注意 不能通过连接其他符号来创建新的操作符比如operator 重载操作符必须有一个类类型参数用于内置类型的运算符其含义不能改变例如内置的整型不能改变其含义作为类成员函数重载时其形参看起来比操作数数目少1因为成员函数的第一个参数为隐藏的this.* :: sizeof ?: . 注意以上5个运算符不能重载。 看一下相等运算符重载的类内和类外实现 这里大家可能会注意到类外实现的operator函数报了好多错误红色波浪线 这是因为我们的成员变量设置的权限为private私有变量不可以在类外使用解决方法除了把函数放到类内实现也可以提供一个获取类内成员变量的函数接口更甚者可以直接把权限改为public上面博主我为了方便就这样写了但是以后工作中如果胆敢这样会让我们的数据安全性降低在公司里可能会吃的。 赋值 下面我们就继续往后讲解 才怪 下面我们回到赋值运算符重载 赋值嘛我们上面就写过了不是为什么还要再写一次呢 欧·吼 那当然是因为上面写的不够好喽。 赋值运算符重载的格式 参数类型const T 使用引用提高传参效率加const防止修改数据 返回值类型T使用运用提高返回效率添加返回值可以实现连续赋值 检测是否自己给自己赋值 返回 *this 要符合连续赋值的含义。 喏我们上面写的只满足第一条的。 不要猜了这个时间是熊猫的生日 赋值运算符只能重载为类的成员函数不能重载为全局函数。 原因赋值运算符重载是类的默认成员函数如果编译器在类中没有找到赋值运算符重载就会提供默认的 结果就是和我们写在全局的发生重载冲突。 有同学就会有疑问了为什么前面的构造、析构和拷贝构造没有提这一点 因为这三个函数更加特殊他们是没有返回值的所以根本就不可能会写在类外。 那么有同学就又有其他疑问了赋值运算符重载只能重载为类的成员函数那么我们上面写的判断相等的重载为什么既可以又可以呢 因为只有赋值运算符重载是默认成员函数如果没编译器会自行提供而其他运算符重载如果程序员不写就真的没有。 程序员没有显示提供时编译器会提供一个默认赋值运算符重载以值的方式逐字节拷贝这里肯定开始会有出现问题的反应快速的同学应该已经联想到了拷贝构造的深浅拷贝。 因此此处也要注意如果类中未涉及资源管理是否自行实现都可以而一旦涉及了资源管理就必须要实现。 前置 后置 Date operator() // 前置{// 前置是先加1后使用因此返回值可以直接返回 *this返回类型为 Date_day;return *this;}// 前置 和后置 都是一元运算符因此无法对它们进行区分// c规定后置重载时多传递一个 int型参数但在函数调用时该参数不需要传递编译器会自行设置// 注意:后置是先使用后因此返回值应该为前的数因此需要创建一个临时变量保存前的数据// 由于返回的是局部变量那么返回时就不能返回引用而要传值返回。Date operator(int){Date tmp *this;_day;return tmp;} 这就结束了嘛没错当然没有 上面我们直接进行可是如果天数大于31我们依然是直接进行天数1吗 那这个时候就需要进行月份进位了。 改进 class Date { public:Date(int year 2023, int month 3, int day 30){_year year;_month month;_day day;}// 判断该月份有多少天int GetMonthDay(){int arr[] { 0,31,28,31,30,31,30,31,31,30,31,30,31 };if (_month 2 ((_year % 4 0 _year % 100 ! 0) || _year % 400 0))arr[2];return arr[_month];}Date operator() // 前置{_day;if (GetMonthDay() _day){_day - GetMonthDay();_month;if(_month 13){_year;_month 1;}}return *this;}Date operator(int){Date tmp *this;*this; // 欧吼复用了上面刚刚写的前置return tmp;}void Print(){cout _year 年 _month 月 _day 日 endl;}private:int _year;int _month;int _day; };void Test02() {Date d1;Date d2 d1;Date d3 d1;d1.Print();d2.Print();d3.Print();}Perfect。 流插入 流提取 现在我们要来了解一下我们经常用到却总是稀里糊涂地就使用起来了的两个运算符。 在C语言中我们输入输出都是通过 scanf 和 printf 两个输入输出函数例如使用printf进行输出是我们需要表明参数的类型 int a, char str[20]; printf(%d %s\n, a, str); 但在c中所有内置类型都可以直接输入输出例如cout a str endl; 之前我们只知道这是c的一个优点使用起来比C语言要方便很多很多那么我要问一问大家cin、cout这么方便的原因到底是什么呢 补充 和 都是运算符 是右移运算符 是左移运算符。 那么既然它们两个是移位操作符那么和输入输出又有什么关系呢 答案就是如果仅仅是作为移位操作符使用那当然是毫无关系的 但是我们上面刚刚看过了运算符重载我们是不是就可以赋予移位运算符新的意义呢 步入正题 ****在c中称为流提取运算符输入从输入设备读取数据 在c中称为流插入运算符输出将内容输出到输出设备 cin是istream类对象cout为ostream类对象i、ostream类型都包含在 iostream 头文件中 而流插入和流1提取都是通过运算符重载来达到输入输出目地的。 而对于自定义类型就需要程序员自行重载下面我们进行尝试 #includeiostream using namespace std;class Date { public:void Print(){cout _year 年 _month 月 _day 日 endl;}void operator(ostream out){out _year 年 _month 月 _day 日 endl;}private:int _year 2023;int _month 3;int _day 8; };void Test02() {Date d1;cout d1; // 错误示范}class Date {friend ostream operator(ostream out, const Date d); public:// friend ostream operator(ostream out, const Date d); // 友元声明可以写在类内任何位置一般写在最上面避免和成员函数声明混淆private:int _year 2023;int _month 3;int _day 8; };ostream operator(ostream out, const Date d) {out d._year 年 d._month 月 d._day 日 endl;return out; }void Test02() {Date d1;//cout d1;//d1 cout; // 成员函数使用形式cout d1 endl d1 endl; // 全局函数使用形式}3、取地址 const取地址 他来了他来了他朝着终点走来了 下面来到取地址操作符重载环节掌声有请重载函数登场~~~ 注意编译器帮我们传过去的this指针可不就是该对象的地址嘛所以直接返回this就好。 上面我们看到输出d1和d2的地址的时候使用的是普通对象取地址但是输出d3的地址的时候需要使用const对象取地址不就是取个地址嘛为什么还要分是不是const对象而且const取地址重载里有一个 const 看起来好像有些 “不合群” 呐孤零零在外面。 注如果声明和定义分离两边都需要加 const。 代码如下 class Date {friend ostream operator(ostream out, const Date d);public:Date(int year 2023, int month 3, int day 8){_year year;_month month;_day day;}void Print(){cout _year 年 _month 月 _day 日 endl;}Date* operator(){return this;}const Date* operator() const{return this;}private:int _year;int _month;int _day; };ostream operator(ostream out, const Date d) {out d._year 年 d._month 月 d._day 日 endl;return out; } 这里的取地址重载基本上不需要我们自行实现除非你不想让对方获取你的地址比如 补充const成员 const修饰的成员函数称之为const成员函数const修饰类成员函数实际修饰该成员函数隐含的this指针 表明在该成员函数中不能对类的任何成员进行修改。 思考下面的几个问题 const对象可以调用非const成员函数吗非const对象可以调用const成员函数吗const成员函数内可以调用其它的非const成员函数吗非const成员函数内可以调用其它的const成员函数吗 回答 const对象不可调用非const成员函数 – 权限扩大非const对象可以调用const成员函数 – 权限缩小const成员函数中不可调用其它的非const成员函数 – 权限扩大 – const成员函数中的this指针为 const类型调用非const成员函数权限或扩大非const成员函数可以调用其它的const成员函数 – 权限缩小。 总结 经过不知道多少多少天的努力终于把类与对象的文章肝出来了啊 本文介绍了类与对象的大部分内容剩余还有一些细枝末节的知识熊猫会在下一篇文章中进行总结 下面对本文所讲内容进行回顾 1. 类的权限 public、protected、private 2. 类的封装、声明、实例化 3. 类大小的计算内存对齐 4. this指针 5. 构造函数的七个特点、析构函数的六个特点 6. 深浅拷贝、赋值 7. 运算符重载前置和后置流插入和流提取运算符重载 8. 取地址运算符重载 9. const成员函数。 以上就是今天c类与对象的全部内容如果有什么疑问或者建议都可以在评论区留言感谢大家对的支持。
文章转载自:
http://www.morning.swbhq.cn.gov.cn.swbhq.cn
http://www.morning.kndst.cn.gov.cn.kndst.cn
http://www.morning.qnkqk.cn.gov.cn.qnkqk.cn
http://www.morning.sgpny.cn.gov.cn.sgpny.cn
http://www.morning.qxljc.cn.gov.cn.qxljc.cn
http://www.morning.rkxk.cn.gov.cn.rkxk.cn
http://www.morning.zwndt.cn.gov.cn.zwndt.cn
http://www.morning.ltypx.cn.gov.cn.ltypx.cn
http://www.morning.zlrrj.cn.gov.cn.zlrrj.cn
http://www.morning.yrcxg.cn.gov.cn.yrcxg.cn
http://www.morning.knpbr.cn.gov.cn.knpbr.cn
http://www.morning.horihe.com.gov.cn.horihe.com
http://www.morning.ktrdc.cn.gov.cn.ktrdc.cn
http://www.morning.ccpnz.cn.gov.cn.ccpnz.cn
http://www.morning.lhztj.cn.gov.cn.lhztj.cn
http://www.morning.nrlsg.cn.gov.cn.nrlsg.cn
http://www.morning.zgpgl.cn.gov.cn.zgpgl.cn
http://www.morning.gtbjc.cn.gov.cn.gtbjc.cn
http://www.morning.qpsdq.cn.gov.cn.qpsdq.cn
http://www.morning.bfrsr.cn.gov.cn.bfrsr.cn
http://www.morning.krhkn.cn.gov.cn.krhkn.cn
http://www.morning.rxkq.cn.gov.cn.rxkq.cn
http://www.morning.qrwnj.cn.gov.cn.qrwnj.cn
http://www.morning.qyqdz.cn.gov.cn.qyqdz.cn
http://www.morning.nrll.cn.gov.cn.nrll.cn
http://www.morning.haibuli.com.gov.cn.haibuli.com
http://www.morning.zynjt.cn.gov.cn.zynjt.cn
http://www.morning.znqztgc.cn.gov.cn.znqztgc.cn
http://www.morning.krdb.cn.gov.cn.krdb.cn
http://www.morning.qjbxt.cn.gov.cn.qjbxt.cn
http://www.morning.tqhpt.cn.gov.cn.tqhpt.cn
http://www.morning.zkdmk.cn.gov.cn.zkdmk.cn
http://www.morning.jsljr.cn.gov.cn.jsljr.cn
http://www.morning.znknj.cn.gov.cn.znknj.cn
http://www.morning.ypqwm.cn.gov.cn.ypqwm.cn
http://www.morning.hrzky.cn.gov.cn.hrzky.cn
http://www.morning.wnqbf.cn.gov.cn.wnqbf.cn
http://www.morning.lkbkd.cn.gov.cn.lkbkd.cn
http://www.morning.tzjqm.cn.gov.cn.tzjqm.cn
http://www.morning.ptdzm.cn.gov.cn.ptdzm.cn
http://www.morning.kfcfq.cn.gov.cn.kfcfq.cn
http://www.morning.jfmjq.cn.gov.cn.jfmjq.cn
http://www.morning.tqdqc.cn.gov.cn.tqdqc.cn
http://www.morning.snxbf.cn.gov.cn.snxbf.cn
http://www.morning.zgdnd.cn.gov.cn.zgdnd.cn
http://www.morning.mfnjk.cn.gov.cn.mfnjk.cn
http://www.morning.cwrpd.cn.gov.cn.cwrpd.cn
http://www.morning.mfnjk.cn.gov.cn.mfnjk.cn
http://www.morning.yfffg.cn.gov.cn.yfffg.cn
http://www.morning.qlpyn.cn.gov.cn.qlpyn.cn
http://www.morning.lmzpk.cn.gov.cn.lmzpk.cn
http://www.morning.lmctj.cn.gov.cn.lmctj.cn
http://www.morning.hrpjx.cn.gov.cn.hrpjx.cn
http://www.morning.hkcjx.cn.gov.cn.hkcjx.cn
http://www.morning.cxnyg.cn.gov.cn.cxnyg.cn
http://www.morning.jqjnx.cn.gov.cn.jqjnx.cn
http://www.morning.tnjff.cn.gov.cn.tnjff.cn
http://www.morning.fhcwm.cn.gov.cn.fhcwm.cn
http://www.morning.nbrdx.cn.gov.cn.nbrdx.cn
http://www.morning.bwjgb.cn.gov.cn.bwjgb.cn
http://www.morning.xznrk.cn.gov.cn.xznrk.cn
http://www.morning.lwsct.cn.gov.cn.lwsct.cn
http://www.morning.skkln.cn.gov.cn.skkln.cn
http://www.morning.plfrk.cn.gov.cn.plfrk.cn
http://www.morning.htmhl.cn.gov.cn.htmhl.cn
http://www.morning.zbjfq.cn.gov.cn.zbjfq.cn
http://www.morning.dwgcx.cn.gov.cn.dwgcx.cn
http://www.morning.gmmxh.cn.gov.cn.gmmxh.cn
http://www.morning.mjats.com.gov.cn.mjats.com
http://www.morning.zgdnd.cn.gov.cn.zgdnd.cn
http://www.morning.rkwwy.cn.gov.cn.rkwwy.cn
http://www.morning.rqmr.cn.gov.cn.rqmr.cn
http://www.morning.npbkx.cn.gov.cn.npbkx.cn
http://www.morning.rwbh.cn.gov.cn.rwbh.cn
http://www.morning.zlrrj.cn.gov.cn.zlrrj.cn
http://www.morning.gfpyy.cn.gov.cn.gfpyy.cn
http://www.morning.gccrn.cn.gov.cn.gccrn.cn
http://www.morning.rwmp.cn.gov.cn.rwmp.cn
http://www.morning.nynlf.cn.gov.cn.nynlf.cn
http://www.morning.kjksn.cn.gov.cn.kjksn.cn
http://www.tj-hxxt.cn/news/261453.html

相关文章:

  • 网站搜什么关键词好怎么注册公司的邮箱
  • 深圳品牌网站制作公司微信网站作用
  • 网站后台无法上传图片网页版qq空间登录
  • 做啊网站wordpress文章页样式
  • 金寨建设工程质量监督站网站计算机毕业设计作品网站
  • 凡科网站怎么做建站广西执业药师培训网站
  • 衡水做外贸网站wordpress 底部
  • 潍坊作风建设网站做图片的网站有哪些
  • 网站开发注意的事项郑州市做网站的
  • 广西住建厅八大员报名网站wordpress 大学 1.3
  • 网站做系统叫什么软件wordpress 自定义域
  • 建网站多少钱建个网站需要怎么做优化公司流程
  • 图书销售网站开发与实现学网页设计怎么样
  • 营销型网站设计注意优质服务的网页归档
  • 有没有做废品的网站两个wordpress共用用户
  • .net做的网站打开速度缓慢免费项目网站
  • 东阳企业网站微商城建设高明网站设计服务
  • 七台河建网站北京建网站开发
  • 有什么网站专门做美食的吗律师网站 扁平化
  • 国内优秀企业网站临高网站建设
  • 深圳企业网站建设服务哪家公司好ppt精美模板
  • 网站建设商务通什么意思做网站手机验证收费吗
  • 知名网站建设公司排名wordpress flash加载
  • 网站开发需求大吗wordpress 文章存档
  • 个人做哪方面的网站潍坊住房与城乡建设局网站
  • 手机网站源码最好网站模板没有html文件下载
  • 政务网站风格网站开源是什么意思
  • 知乎网站内容建设的逻辑湖南网站网络推广哪家奿
  • 建筑网站案例qq建设网站首页
  • 广东省住房城乡建设厅网站做网站常熟