类成员函数解析

 

1、  构造函数:

(1)      定义:是一个特殊的成员函数,名字与类名相同,创建类类型对象时,由编译器自动调用,在对象的生命周期内只且只调用一次,以保证每个数据成员都有一个合适的初始值。

(2)      特性:

1、函数名与类名相同。

2、没有返回值。

3、有初始化列表(可以不用)。

4、新对象被创建,由编译器自动调用,且在对象的生命期内仅调用一次。

5、构造函数可以重载,实参决定了调用那个构造函数。

6、如果没有显式定义时,编译器会提供一个默认的构造函数。

7、无参构造函数和带有缺省值得构造函数都认为是缺省构造函数,并且缺省构造函数只能有一个。

(3)分类:

 

无参构造函数:如果没有显式的定义一个构造函数,系统将默认合成一个无参构造函数,参数为空,什么都不做。

 

显式的定义一个无参构造函数,如下例:

    Time()

    {

       cout<<"Time(int intint )"<<endl;

    }

 

普通构造函数(也称重载构造函数):

class Time

{

public:

    Time(int h, int m, int s)

    {

       _hour = h;

       _minute = m;

       _second = s;

       cout<<”Time(int, int, int)”<<endl;

    }

private:

    int _hour;

    int _minute;

    int _second;

};

 

 

系统默认合成的构造函数:在A类有缺省的构造函数,B类没有显示的定义构造函数,B类中含有A类类型成员,此时系统默认合成构造函数。

class Time

{

public:

 

    Time()

    {

       cout<<"Time(int intint )"<<endl;

    }

private:

    int _hour;

    int _minute;

    int _second;

};

class Date

{

private:

    int _year;

    int _month;

    int _day;

    Time t;

 

};

 

 

运行结果:

 

 

 

 

初始化列表:

以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每个数据成员后面跟一个放在园括号中的初始化式。

classDate

{

public:

     Date(int year = 1, int month = 2, int day = 3)

       :_year(year),

       _month(month),

       _day(day)

       {

           cout<<"Date(int, int, int)"<<endl;

       }

private:

    int _year;

    int _month;

    int _day;

 

};

初始化顺序:

 

1、初始化列表仅用于初始化数据成员,并不指定这些数据成员的初始化顺序,数据成员在类中定义顺序就是在参数列表中的初始化顺序。

 

2、每个成员在初始化列表中只能出现一次,尽量避免使用成员初始化成员,成员的初始化顺序最好和成员的定义顺序保持一致。

 

类中包含以下成员必须要放在初始化列表中初始化:

class Time

{

public:

    //Time()

    //{}

    Time(int h, int m, int s)

    {

       cout<<"Time(int intint )"<<endl;

    }

private:

    int _hour;

    int _minute;

    int _second;

};

 

class Date

{

public:

     Date(int year, int month, int day)

       :_year(year),

       _month(month),

       _day(day),

       t(0, 0, 0)

       {

           cout<<_year<<"-"<<_month<<"-"<<_day<<endl;

       }

private:

    int _year;

    int _month;

    int _day;

    const int a;

    int& b;

};

1、引用数据成员

2、const数据成员

 



 

3、类类型成员(该类没有缺省的构造函数):Time类中没有缺省的构造函数(无参构造函数,有参数,但有缺省的构造函数),要调用Date类创建对象,则类内的成员都要初始化,Date类中含有Time类类型成员,只能在初始化列表内进行初始化

 


 

 

 

 

 

2、  拷贝构造函数

显式的定义拷贝构造函数:

class Date

{

public:

     Date(int year = 1, int month = 2, int day = 3)

       :_year(year),

       _month(month),

       _day(day)

       {

           cout<<"Date(int, int,int)"<<endl;

       }

     Date(const Date &d)

       :_year(d._year),

       _month(d._month),

       _day(d._day)

     {

       cout<<"Date(&d)"<<endl;

     }

 

private:

    int _year;

    int _month;

    int _day;

};

void FunTest()

{

    Date d;

    Date d1(d);

}

运行结果:

       系统默认合成拷贝构造函数:在A类有缺省的构造函数,B类没有显示的定义拷贝构造函数,B类中含有A类类型成员,此时系统默认合成拷贝构造函数。

class Time

{

public:

 

    Time()

    {

       cout<<"Time(int intint )"<<endl;

    }

private:

    int _hour;

    int _minute;

    int _second;

};

class Date

{

public:

     Date(int year = 1, int month = 2, int day = 3)

       :_year(year),

       _month(month),

       _day(day)

       {

           cout<<"Date(int, int,int)"<<endl;

       }

 

private:

    int _year;

    int _month;

    int _day;

    Time t;

};

void FunTest()

{

    Date d;

    Date d1(d);

}

运行结果:

 

3、  析构函数:与构造函数功能相反,在对象被销毁时,由编译器自动调用,完成类的一些资源清理和汕尾工作

 

析构函数特性:

a、析构函数在类名(即构造函数名)加上字符~。

b、析构函数无参数无返回值。

c、一个类有且只有一个析构函数。若未显示定义,系统会自动生成缺省的析构函数。

d、对象生命周期结束时,C++编译系统系统自动调用析构函数。

e、注意析构函数体内并不是删除对象,而是做一些清理工作

 

class Date

{

public:

    Date(int year, int month, int day)

       : _year(year)

       , _month(month)

       , _day(day)

    {

       cout<<"Date(int, int,int):"<<this<<endl;

    }

 

    Date(const Date& d)

       : _year(d._year)

       , _month(d._month)

       , _day(d._day)

    {

       cout<<"Date(constDate& d):"<<this<<endl;

    }

 

    Date& operator=(const Date& d)

    {

       cout<<"Date&operator=(const Date& d):"<<this<<endl;

       if (this != &d)

       {

           _year = d._year;

           _month = d._month;

           _day = d._day;

       }

 

       return *this;

    }

 

    ~Date()

    {

       cout<<"~Date():"<<this<<endl;

    }

 

private:

    int _year;

    int _month;

    int _day;

};

 

void FunTest()

{

    Date d(2016, 10, 17);

    Date d1(d);

}

运行结果:



析构函数销毁对象原则:先构造后析构,后构造先析构。

 

赋值运算符重载:

 

      在面向对象程序设计中,对象间的相互拷贝和赋值是经常进行的操作,如果对象在申明的同时马上进行的初始化操作,则称之为拷贝运算。例如:
       class A(“Date”) ;  class B = A;
     此时其实际调用的是B(A)这样的浅拷贝操作。


    如果对象在申明之后,在进行的赋值运算,我们称之为赋值运算。例如:
        class  A("Date");  class B;
        B=A;
        此时实际调用的类的缺省赋值函数B.operator=(A);

 

class Date

{

public:

    Date(int year = 2016, int month = 10 , int day = 1)

       : _year(year)

       , _month(month)

       , _day(day)

    {

       cout<<"Date(int, int,int):"<<this<<endl;

    }

 

    Date(const Date& d)

       : _year(d._year)

       , _month(d._month)

       , _day(d._day)

    {

       cout<<"Date(constDate& d):"<<this<<endl;

    }

 

    Date& operator=(const Date& d)

    {

       cout<<"Date&operator=(const Date& d):"<<this<<endl;

       if (this != &d)

       {

           _year = d._year;

           _month = d._month;

           _day = d._day;

       }

       return *this;

    }

 

    ~Date()

    {

       cout<<"~Date():"<<this<<endl;

    }

 

private:

    int _year;

    int _month;

    int _day;

};

void FunTest()

{

    Date d(2016, 10, 17);

Date d1(d); // 调用拷贝构造函数进行拷贝

Date d2;

    D2 = d;    //d1.operator(&d)赋值运算符重载

}


程序编译之后,d1 和 d2 在栈上都分配了内存,,对象d1 的域被初始化,d2为随机值。

如果我们简单的执行Date d1(d); 即 Date d1 = d; 则其执行的是缺省定义的缺省的赋值运算。所谓缺省的赋值运算,是指对象中的所有位于stack中的域,进行相应的复制。但是,如果对象有位于heap上的域的话,其不会为拷贝对象分配heap上的空间,而只是指向相同的heap上的同一个地址。


因此,对于缺省的赋值运算,如果对象域内没有heap上的空间,其不会产生任何问题。但是,如果对象域内需要申请heap上的空间,那么在析构对象的时候,就会连续两次释放heap上的同一块内存区域,从而导致异常。

 

故需要用赋值运算符重载

 

Date d2;

    D2 = d;    //d1.operator(&d)赋值运算符重载

 

  Date& operator=(const Date& d)

    {

       cout<<"Date&operator=(const Date& d):"<<this<<endl;

        if (this != &d)

       {

           _year = d._year;

           _month = d._month;

           _day = d._day;

       }

       return *this;

  }//一定要返回引用,否则返回其值后立即消失,不能连续赋值

 




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

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

相关文章

微信开发学习日记(六):weiphp框架

最近重点在看weiphp这个开源的第三方微信公众平台框架。在网上找微信资料&#xff0c;找到了这个。很早之前&#xff0c;就初步学习了Thinkphp和Onethink2个开源框架&#xff0c;当看到weiphp是用这2个框架开发的时候&#xff0c;我就更愿意去学习&#xff0c;毕竟学习成本很低…

SVN常用命令备注

1、将文件checkout到本地目录 svn checkout path&#xff08;path是服务器上的目录&#xff09; 例如&#xff1a;svn checkout svn://192.168.1.1/pro/domain 简写&#xff1a;svn co 2、往版本库中添加新的文件 svn add file 例如&#xff1a;svn add test.php(添加test.php)…

add-apt-repository cloud-archive:liberty

apt-get update && apt-get upgrade; v

日期类Date

#include <iostream>using namespace std;//日期是否合法//日期比较//两个日期中间差的天数//日期加上或减去一定的天数后的日期class Date{friend ostream& operator<<(ostream& _cout, const Date& d);friend istream& operator>>(istream…

Linux下编译安装Apache httpd 2.4

Apache是世界使用排名第一的Web服务器软件。它可以运行在几乎所有广泛使用的计算机平台上&#xff0c;由于其跨平台和安全性被广泛使用&#xff0c;是最流行的Web服务器端软件之一。当前Apache版本为2.4&#xff0c;本文主要描述基于CentOS 6.5以源码方式安装Apache httpd。 一…

选取硬币问题

有1元&#xff0c;5元&#xff0c;10元&#xff0c;50元&#xff0c;100元&#xff0c;500元的硬币各c0,c1,c2,c3,c4, c5枚 现在要使用这些硬币支付n元&#xff0c;问最少需要多少枚硬币&#xff0c;假设至少存在一种方案。 应该尽可能使用500元的&#xff0c;然后再使用100元的…

SAP OBYC自动记账的实例说明 +VALUE STRING

对Value String定义&#xff1a;定义了一系列的步骤优先顺序&#xff0c;每一个步骤都连接到不同的过账事务码&#xff0c;而这个顺序本身就称作价值串。价值串你可以看作是一种记账的规则&#xff0c;为物料移动或者发票校验包含了一系列的科目分配特征。并且物料移动的科目确…

C++ 继承解析

继承 1、概念&#xff1a; 继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段&#xff0c;它允许程序员在保持原有类特性的基础上进行扩展&#xff0c;增加功能。这样产生新的类&#xff0c;称派生类。继承呈现了面向对象程序设计的层次结构&#xff0c;体…

javascript window.open

翻译原文&#xff1a;open methodOpens a new window and loads the document specified by a given URL.Navigates the app window to the specified location.Syntaxvar retval window.open(url, name, features, replace);Parametersurl [in, optional] Type: String …

[傅里叶变换及其应用学习笔记] 九. 继续卷积的讨论

这份是本人的学习笔记&#xff0c;课程为网易公开课上的斯坦福大学公开课&#xff1a;傅里叶变换及其应用。 卷积在滤波中的应用 浑浊度&#xff08;Turbidity&#xff09;研究是关于测量水的清澈度的研究。大致方法是把光传感器放置到深水区域&#xff0c;然后测量光线的昏暗程…

C++多态相关关问题及虚表剖析

关于C多态的问题&#xff1a;&#xff08;基于Visual Studio 2012编译器&#xff09; 一、多态引入 1、对象的类型&#xff1a; &#xff08;1&#xff09; 静态的类型&#xff1a;对象声明时的类型&#xff0c;在编译的时候确定 &#xff08;2&#xff09; 动态的类型&…

C++调用约定

<div class"markdown_views"><p>有一定C开发经验的人一定对”__cdecl、__stdcall、__fastcall”肯定不陌生吧&#xff01;但你真正理解了吗&#xff1f;是的&#xff0c;我曾在这采了无数个坑&#xff0c;栽了无数个跟头&#xff0c;终于忍无可忍要把它总…

CSS中的特殊的选择器

/*表示div盒子中的P标签*/ div P{} /*表示div盒子中除第一个P之外的都要添加样式*/ div pp{} /*表示div盒子中从第三个p开始都要添加样式*/转载于:https://www.cnblogs.com/Dream-Seeker/p/4454325.html

添加文字和水印

1.加文字-(UIImage *)addText:(UIImage *)img text:(NSString *)text1{//get image width and heightint w img.size.width;int h img.size.height;CGColorSpaceRef colorSpace CGColorSpaceCreateDeviceRGB();//create a graphic context with CGBitmapContextCreateCGCont…

C++动态绑定及返回类型协变

C多态之动态绑定&#xff1a; 1、概念&#xff1a;在程序执行期间(非编译期)判断所引用对象的实际类型&#xff0c;根据其实际类型调用相应的方法。 使用virtual关键字修饰类的成员函数时&#xff0c;指明该函数为虚函数&#xff0c;派生类需要重新实现&#xff0c;编译器将实…

使用ucontext组件实现的coroutine代码分析

coroutine一般翻译过来就是协程&#xff0c;类似于线程可以切换&#xff0c;而跟线程是由操作系统调度器来实现切换不一样&#xff0c;协程由用户程序自己调度进行切换。我以前也看过协程相关的内容&#xff0c;但没有自己去实现过。最近搞OpenStack&#xff0c;OpenStack各个模…

C++模板剖析:函数模板、类模板解析

C中关于模板&泛型编程问题&#xff1a; 问题引入&#xff1a;何编写一个通用加法函数&#xff1f; &#xff08;1&#xff09;使用函数重载&#xff0c;针对每个所需相同行为的不同类型重新实现它 int Add(const int &_iLeft, const int&_iRight) { return (_iL…

Android Studio 1.1的安装和遇到的坑

Google的Android Studio 出1.0稳定版本也有很久的时间了&#xff0c;一直喜欢Jetbrains公司的IDE&#xff0c;不同语言的IDE操作习惯都比较统一。 而Android Studio 是基于IntelliJ IDEA的社区版开发的 &#xff0c;怎么也要尝尝鲜才行。 今天安装了下&#xff0c;被几个小坑卡…

Linux:Access time、 Modify time 、Change time 和 find 命令使用解析

一、Access time 、Modify time 、Change time 1、含义&#xff1a; Access&#xff1a;是指“访问时间” 对于文件&#xff0c;用编辑器打开file&#xff0c;或使用cat more less grep sed 等等命令读取文件内容&#xff0c;以及使用file cp命令操作文件&#xff0c;或执行…