3_V1-类和对象 -- 默认成员函数

定义一个日期类

#include <iostream>
#include <assert.h>
using namespace std;class Date
{
public:void Display();
private:int _year;int _month;int _day;
};

注意:

在定义一个类的时候往往会将其成员变量定义为私有,成员函数定义为公有.这是为了达到软件工程上的高内聚低耦合的要求

this指针

每一个函数都有自己的形式指针,它的名字是固定的,称为this,同时this指针是隐式的.
编译器会对成员函数进行优化,在对象调用成员函数的时候,此时会将该对象的地址传递给成员函数的第一个参数
同时this指针是成员函数隐含指针参数,我们程序员不能自己将其加到成员函数的形式参数列表中,也不能在调用的时候显示的将对象的地址传给this指针
这里写图片描述

注意:

this指针是形式参数,既然是形式参数那么它就会在栈上,但是在Linux下,this指针是被存放在寄存器中.同时谁来调用this成员函数那么this指针就指向谁

构造函数

构造函数可以达到原子性,即对象被定义的时候就会被初始化.在定义类的时候我们呢看到通常会将成员函数定义为私有但是私有成员变量在类外是不能被访问的.为了对成员函数进行初始化,此时就需要构造函数来对私有成员变量进行初始化.同时构造函数只在对象被定义的时候仅仅被执行一次.下面来说一下构造函数的特点
1.函数名和类名相同
2.无返回值
3.对象构造时系统自己调用对应的构造函数
4.构造函数可以重载(函数名相同, 参数不同)
5.构造函数可以在类里面定义也可以在类外面定义
6.如果类中没有定义一个构造函数,系统会默认生成一个缺省的构造函数,但是当我们定义了构造函数,此时系统就不会生成默认的缺省构造函数,而会定义我们自己定义的构造函数,编译器在对其进行初始化的时候,内置的类型会被初始化,但是自定义的不会进行初始化
7.无参的构造函数和全缺的构造函数都认为是缺省构造函数.并且缺省的构造函数只能有一个

几种构造函数

class Date
{
public:// 1.无参的构造函数// Date()// {// }// 2.缺省构造函数Date(int year = 1900, int month = 1, int day = 1){if(year < 1900 || month < 0 || month > 12 || day < 0 || day > 31){assert(0);}_year = year;_month = month;_day = day;}//3. 带参的构造函数// Date (int year, int month, int day)// {//     _year = year;//     _month = month;//     _day = day;// }// 4. 拷贝构造函数,创建一个对象Date(Date& d){_year = d._year;_month = d._month;_day = d._day;}void Display();
private:int _year;int _month;int _day;
};

注意:

拷贝构造其实就可以理解为一种特殊的构造函数,它是构造函数的重载,同时注意拷贝构造是对象的创建,而我们后面将所说的赋值是两个对象都已经存在
同时拷贝构造必须传引用,因为如果传值的话那么就会出现无穷递归(拷贝构造就要传参,传参就要拷贝构造)
3.如果自己没有显示进行定义,那么系统就会自己生成默认缺省构造函数.缺省的时候拷贝构造函数就会依次拷贝类成员进行初始化

析构函数

1.和类的名字前面加上一个~
2.无返回值
3.一个类有且只有一个析构函数(因为没有参数,不能构成重载),如果我们自己不写编译器会自动生成
4.对象生命周期结束的时候,系统调用析构函数
5.析构函数不能删除对象,只是对对象进行清理

注意:

如果需要清理成员变量(动态开辟空间),则自己写析构函数,对象在定义的时候一定调用了构造,生命周期结束的时候就一定调用了析构函数

运算符重载

Date& operator = (const Date& d){this -> _year = d._year;this -> _month = d._month;this -> _day = d._day;return *this;}// d2 == d3// d2.operator(*this, d3)bool operator == (const Date& d) {if(this -> _year == d._year && this -> _month == d._month && this -> _day == _day){return true;}return false;}bool operator != (const Date d){if(!(*this == d)){return true;}return false;}//d1 > d2//d1.operator > (this, d2)bool operator > (const Date& d) {if(this -> _year > d._year){return true;}if(this -> _year == d._year){if(this -> _month > d._month){return true;}}if(this -> _month == d._month){if(this -> _day > d._day){return true;}}return false;}//d2 < d3//d2.operator(this, d3)bool operator < (const Date& d) {if(*this == d || *this > d){return false;}return true;}// d2 >= d3bool operator >= (const Date& d){if(*this > d || *this == d){return true;}return false;}//d2 <= d3bool operator <= (const Date& d){if(*this < d || *this == d){return true;}return false;}//d2++Date& operator ++ () // 前置 {++( this -> _day );if(this -> _day > GetMonthDay(this -> _year, this -> _month)){this -> _day = 1;++(this -> _month);if((this -> _month) > 12){++(this -> _year);this -> _month = 1;}}return *this;}//d2++Date operator ++ (int) // 后置 {Date ret = (*this);++( *this );return ret;}//2018-1-1Date& operator -- (){--(this -> _day);if(this -> _day == 0){(this -> _month)--;if(this -> _month == 0){this -> _year -= 1;this -> _month = 12;}(this -> _day) += GetMonthDay(this -> _year, this -> _month);}return *this;}Date operator -- (int)//后置{Date ret = *this;--(*this);return ret;}Date& operator += (int day){this -> _day = this -> _day + day;while(this -> _day > GetMonthDay(this -> _year, this -> _month)){this -> _day = this -> _day - GetMonthDay(this -> _year, this -> _month);this -> _month ++;if(this -> _month > 12){this -> _month = 1;this -> _year ++;}}return *this;}//d1 + 30//d1.operator(this, day)Date operator + (int day) {Date ret = *this;ret += day;return ret;}Date& operator -= (int day){this -> _day -= day;while(this -> _day <= 0){this -> _month --;if(this -> _month < 1){this -> _month = 12;this -> _year --;}this -> _day += GetMonthDay(this -> _year, this -> _month);}return *this;}Date operator - (int day){Date ret = *this;ret -= day;return ret;}// 2018-1-31  -  2018-1-1// d1.operator(this, d2)int operator - (const Date& d){int count = 0;//记录天数while(*this > d){--(*this);( *this ).Display();++count;}return count;}void Display()//展示日期类{cout<<_year<<"-"<<_month<<"-"<<_day<<endl;}int GetMonthDay(int year, int month){int day[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};if(( year %4 == 0 && year % 100 != 0 ) || ( year % 400 == 0 )){day[month] = day[2] + 1;}return day[month];}

输入探索构造函数

类的成员函数有两种初始化方式
1.初始化列表
以一个冒号开始, 接着一个逗号分隔数据列表, 每个数据成员都在括号里进行初始化. 尽量使用初始化列表, 因为初始化列表更加高效.
2.构造函数体内进行赋值
这里写图片描述
初始化列表为什么更加高效
1.初始化列表不写, 编译器会自动走一次(自定义成员变量)
2.初始化列表可以认为是成员变量定义的地方
3.构造函数体内赋值会产生临时变量, 但是初始化列表不会产生临时变量

那些成员变量必须放在初始化列表中

1.常量成员变量(常量创建时必须初始化)
2.引用类型成员变量(引用成员变量创建时必须初始化)
3.没有缺省构造函数的自定义类型
4.成员变量初始化的时候按照声明顺序依次初始化,而非初始化列表出现的顺序

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/383919.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HDU - 2973威尔逊定理

核心问题就是那个等式 我们观察到等式可以写成(n-1)!-1/n-[(n-1)!/n]的形式&#xff0c;这样就应该联想到威尔逊定理了。 回顾一下威尔逊定理的内容&#xff1a;当且仅当n为素数的时候n|(n-1)!-1&#xff0c;n为合数且大于4的时候n|(n-1)!【参见威尔逊定理的证明】 对于这个…

linux网络编程之posix 线程(四):posix 条件变量与互斥锁 示例生产者--消费者问题

http://blog.csdn.net/jnu_simba/article/details/9129939 一、posix 条件变量 一种线程间同步的情形&#xff1a;线程A需要等某个条件成立才能继续往下执行&#xff0c;现在这个条件不成立&#xff0c;线程A就阻塞等待&#xff0c;而线程B在执行过程中使这个条件成立了&#x…

3-V2-类和对象 -- const内联 静态成员 友元

const修饰成员函数 在成员函数后面加一个const, const修饰this指针指向的对象, 保证调用这个const成员函数的对象在函数内不会被改变 注意:成员函数如果不修改成员变量,则加上const,成员函数如果要修改成员变量,此时就不能给其加上const修饰了 1.const对象不能调用非const…

C语言 二级指针内存模型混合实战

http://www.cnblogs.com/zhanggaofeng/p/5485833.html //二级指针内存模型混合实战 #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <string.h>//将内存模型①和内存模型②的数据拷贝到内存模型③ char ** threemodel(ch…

Linux 网络编程八(epoll应用--大并发处理)

http://www.cnblogs.com/zhanggaofeng/p/5901316.html //头文件 pub.h #ifndef _vsucess#define _vsucess#ifdef __cplusplus extern "C" {#endif //服务器创建socket int server_socket(int port);//设置非阻塞 int setnonblock(int st);//接收客户端socket int ser…

【数据结构与算法】内部排序之三:堆排序(含完整源码)

转载请注明出处&#xff1a;http://blog.csdn.net/ns_code/article/details/20227303 前言 堆排序、快速排序、归并排序&#xff08;下篇会写这两种排序算法&#xff09;的平均时间复杂度都为O&#xff08;n*logn&#xff09;。要弄清楚堆排序&#xff0c;就要先了解下二叉堆这…

模线性方程(中国剩余定理+扩展中国剩余定理)

已知一系列除数和模数,求最小的满足条件的数 我们先考虑一般的情况&#xff0c;即模数不互质。&#xff08;扩展中国剩余定理&#xff09; 我们考虑两个方程的情况 x%MR xk1∗MRxk1 * MRxk1∗MR x%mr xk2∗mrxk2 * mrxk2∗mr 所以k1∗MRk2∗mrk1 * MRk2 * mrk1∗MRk2∗mr 即…

【数据结构】(面试题)使用两个栈实现一个队列(详细介绍)

http://blog.csdn.net/hanjing_1995/article/details/51539578 使用两个栈实现一个队列 思路一&#xff1a; 我们设定s1是入栈的&#xff0c;s2是出栈的。 入队列&#xff0c;直接压到s1即可 出队列&#xff0c;先把s1中的元素倒入到s2中&#xff0c;弹出s2中的栈顶元素&#x…

C++::探索对象模型

前面我们已经知道, 在没有虚函数的时候, 对象的大小就是对应的成员变量的大小, 而成员函数不会占用对象的空间, 今天我们来讨论一下, 当类中定义了虚函数的时候, 此时对象的大小以及对象模型 非继承下的对象模型 class Base { public:virtual void func1(){cout << &qu…

软件测试相关概念

什么叫软件测试 软件测试就是测试产品没有错误,同时又证明软件是可以正确运行的 测试和调试的区别 调试一般都在开发期间 ,测试是伴随着整个软件的生命周期, 调试是发现程序中问题并且解决问题, 测试是发现程序中的缺陷 软件测试的目的和原则 目的:验证软件有没有问题 原…

C++静态成员函数访问非静态成员的几种方法

https://www.cnblogs.com/rickyk/p/4238380.html 大家都知道C中类的成员函数默认都提供了this指针&#xff0c;在非静态成员函数中当你调用函数的时候&#xff0c;编译器都会“自动”帮你把这个this指针加到函数形参里去。当然在C灵活性下面&#xff0c;类还具备了静态成员和静…

HDU2683——欧拉完全数

题目要求符合等式的数&#xff0c;我们首先要做的就是分析这个数&#xff1a; 对于这个等式&#xff0c;我们可能什么都看不出来&#xff0c;左边很难化简的样子&#xff0c;所以我们就要想到通过变化怎么样把右边化成和左边形式差不多的样子。结合组合数我们想到二项式定理&am…

获取网络接口信息——ioctl()函数与结构体struct ifreq、 struct ifconf

http://blog.csdn.net/windeal3203/article/details/39320605 Linux 下 可以使用ioctl()函数 以及 结构体 struct ifreq 结构体struct ifconf来获取网络接口的各种信息。 ioctl 首先看ioctl()用法ioctl()原型如下&#xff1a;#include <sys/ioctl.h>int ioctl(int fd, i…

java中引用传递

基本概念 栈内存 所谓的栈内存就是存储进程在运行过程中变量的内存空间 堆内存 所谓的堆内存就是存储系统中数据的内存空间 数组相关的引用传递 先来看一段代码 public class ArrayDemo {public static void main(String[] args) {int[] x null;x new int[3];System.o…

(原创)C++11改进我们的程序之右值引用

http://www.cnblogs.com/qicosmos/p/3369940.html 本次主要讲c11中的右值引用&#xff0c;后面还会讲到右值引用如何结合std::move优化我们的程序。 c11增加了一个新的类型&#xff0c;称作右值引用(R-value reference)&#xff0c;标记为T &&&#xff0c;说到右值引用…

(原创)C++11改进我们的程序之move和完美转发

http://www.cnblogs.com/qicosmos/p/3376241.html 本次要讲的是右值引用相关的几个函数&#xff1a;std::move, std::forward和成员的emplace_back&#xff0c;通过这些函数我们可以避免不必要的拷贝&#xff0c;提高程序性能。move是将对象的状态或者所有权从一个对象转移到另…

微型个人博客服务器

Http相关简介 Http是应用层的基于请求响应的一个协议, 其中Http的请求响应可以分为四部分. 请求行, 请求报头,空行, 请求正文.其中请求行包括了请求方法, url, 版本号, 请求报头包括请求属性, 冒分割的键值对, 每组属性之间都以换行的形式分开, 最后一空行作为请求的结束标识.…

[C/C++]关于C++11中的std::move和std::forward

http://blog.sina.com.cn/s/blog_53b7ddf00101p5t0.htmlstd::move是一个用于提示优化的函数&#xff0c;过去的c98中&#xff0c;由于无法将作为右值的临时变量从左值当中区别出来&#xff0c;所以程序运行时有大量临时变量白白的创建后又立刻销毁&#xff0c;其中又尤其是返回…

Linux I/O复用之select函数详解

http://blog.csdn.net/y396397735/article/details/55004775 select函数的功能和调用顺序 使用select函数时统一监视多个文件描述符的&#xff1a; 1、 是否存在套接字接收数据&#xff1f; 2、 无需阻塞传输数据的套接字有哪些? 3、 哪些套接字发生了异常&#xff1f; sel…

深入研究socket编程(3)——使用select函数编写客户端和服务器

http://blog.csdn.net/chenxun_2010/article/details/50488394 首先看原先《UNIX网络编程——并发服务器&#xff08;TCP&#xff09;》的代码&#xff0c;服务器代码serv.c&#xff1a; [cpp] view plaincopy #include<stdio.h> #include<sys/types.h> #inclu…