首页新闻动态正文

C++学习5:类的构造函数【黑马C++培训】

更新时间:2019年08月02日 16时00分55秒 来源:黑马程序员论坛

黑马中级程序员课程

之前在本科的C++学习中,只记得对类进行定义和成员的调用,由于没有具体实践,大作业也很水,对构造函数欠缺理解,接下来就来学习构造函数。 构造函数的作用 首先来看构造函数的作用。类的结构类似于结构体,对于结构体是可以直接进行初始化的,比如: struct Date {     int year;     int month;     int day; }; Date test = {2017,7,12}; 而对于类,一般是不可以直接初始化的,其原因在于,类中可能有私有成员。也就是说,当所有成员变量都是公有的,那OK,直接初始化是可以的;而如果存在私有成员,则无法直接初始化。因此出现了构造函数。 简单的来说,构造函数就是为了解决类的初始化问题,在使用类声明对象时,会自动调用构造函数进行初始化。 构造函数的定义 构造函数是类中的一个成员函数,与类同名。以下面代码为例,看下构造函数的定义。 class TComMv { private:   Short m_iHor;     ///< horizontal component of motion vector   Short m_iVer;     ///< vertical component of motion vector public:   TComMv() //无参构造函数   {       m_iHor = 0;       m_iVer = 0;   }   TComMv( Short iHor, Short iVer ) //有参构造函数   {       m_iHor = iHor;       m_iVer = iVer;   } } 需要注意的是,构造函数的参数名不能与类成员变量同名,也就是示例中的TComMv( Short iHor, Short iVer )的参数iHor、iVer不能使用m_iHor、m_iVer,否则会造成错误。 构造函数可以通过以上的方式在类中定义,也可以作为一个函数,在类中声明,在类外进行定义。例如:   TComMV::TComMv( Short iHor, Short iVer )   {       m_iHor = iHor;       m_iVer = iVer;   } 构造函数是一种特殊的成员函数,用户不需要调用,也不可以调用它,他会在建立类的时候自动执行。 默认构造函数 在创建一个类时,如果用户没有定义构造函数,那么系统会自动生成一个无参构造函数,函数体为空,作为默认构造函数,在用户创建类时自动调用。   TComMv()   {   } 默认构造函数只有在没有定义构造函数的情况下,系统才会自动定义。因此为了防止出错,在定义了有参构造函数时,最好定义无参构造函数。 构造函数初始化列表 推荐阅读: http://blog.csdn.net/ianchoi/article/details/6917899 在很多程序代码中,并不使用上述方法定义构造函数,而是采用初始化列表的形式来定义,还是刚才的那个例子,换用初始化列表定义如下: class TComMv { private:   Short m_iHor;     ///< horizontal component of motion vector   Short m_iVer;     ///< vertical component of motion vector public:   TComMv() :   m_iHor(0),   m_iVer(0)   {   }   TComMv( Short iHor, Short iVer ) :   m_iHor(iHor),   m_iVer(iVer)   {   } 初始化列表是将初始化的成员列表放在了函数名之后,用冒号隔开,采用变量的括号()赋值方法来对成员进行赋值。 下面直接借用http://blog.csdn.net/ianchoi/article/details/6917899的内容。 其带来的好处有两点: 1.设想你有一个类成员,它本身是一个类或者结构,而且只有一个带一个参数的构造函数。 class CMember { public:     CMember(int x) { ... } }; 因为Cmember有一个显式声明的构造函数,编译器不产生一个缺省构造函数(不带参数),所以没有一个整数就无法创建Cmember的一个实例。 CMember* pm = new CMember; // Error!! CMember* pm = new CMember(2); // OK 如果Cmember是另一个类的成员,你怎样初始化它呢?你必须使用成员初始化列表。 class CMyClass {     CMember m_member; public:     CMyClass(); }; //必须使用成员初始化列表 CMyClass::CMyClass() : m_member(2) { ... } 没有其它办法将参数传递给m_member,如果成员是一个常量对象或者引用也是一样。根据C++的规则,常量对象和引用不能被赋值,它们只能被初始化。 2.出于效率考虑,当成员类具有一个缺省的构造函数和一个赋值操作符时。MFC的Cstring提供了一个完美的例子。假定你有一个类 CmyClass具有一个Cstring类型的成员m_str,你想把它初始化为 “yada yada. “。你有两种选择: CMyClass::CMyClass() { // 使用赋值操作符 // CString::operator=(LPCTSTR); m_str = _T( "yada yada "); } //使用类成员列表 // and constructor CString::CString(LPCTSTR) CMyClass::CMyClass() : m_str(_T( "yada yada ")) { } 在 它们之间有什么不同吗?是的。编译器总是确保所有成员对象在构造函数体执行之前初始化,因此在第一个例子中编译的代码将调用CString:: Cstring来初始化m_str,这在控制到达赋值语句前完成。在第二个例子中编译器产生一个对CString:: CString(LPCTSTR)的调用并将 “yada yada “传递给这个函数。结果是在第一个例子中调用了两个Cstring函数(构造函数和赋值操作符),而在第二个例子中只调用了一个函数。在 Cstring的例子里这是无所谓的,因为缺省构造函数是内联的,Cstring只是在需要时为字符串分配内存(即,当你实际赋值时)。但是,一般而言, 重复的函数调用是浪费资源的,尤其是当构造函数和赋值操作符分配内存的时候。在一些大的类里面,你可能拥有一个构造函数和一个赋值操作符都要调用同一个负责分配大量内存空间的Init函数。在这种情况下,你必须使用初始化列表,以避免不要的分配两次内存。在内部类型如ints或者longs或者其它没有构造函数的类型下,在初始化列表和在构造函数体内赋值这两种方法没有性能上的差别。不管用那一种方法,都只会有一次赋值发生。

推荐了解热门学科

java培训 Python人工智能 Web前端培训 PHP培训
区块链培训 影视制作培训 C++培训 产品经理培训
UI设计培训 新媒体培训 产品经理培训 Linux运维
大数据培训 智能机器人软件开发




传智播客是一家致力于培养高素质软件开发人才的科技公司“黑马程序员”是传智播客旗下高端IT教育品牌。自“黑马程序员”成立以来,教学研发团队一直致力于打造精品课程资源,不断在产、学、研3个层面创新自己的执教理念与教学方针,并集中“黑马程序员”的优势力量,针对性地出版了计算机系列教材50多册,制作教学视频数+套,发表各类技术文章数百篇。

传智播客从未停止思考

传智播客副总裁毕向东在2019IT培训行业变革大会提到,“传智播客意识到企业的用人需求已经从初级程序员升级到中高级程序员,具备多领域、多行业项目经验的人才成为企业用人的首选。”

中级程序员和初级程序员的差别在哪里?
项目经验。毕向东表示,“中级程序员和初级程序员最大的差别在于中级程序员比初级程序员多了三四年的工作经验,从而多出了更多的项目经验。“为此,传智播客研究院引进曾在知名IT企业如阿里、IBM就职的高级技术专家,集中研发面向中高级程序员的课程,用以满足企业用人需求,尽快补全IT行业所需的人才缺口。

何为中高级程序员课程?

传智播客进行了定义。中高级程序员课程,是在当前主流的初级程序员课程的基础上,增加多领域多行业的含金量项目,从技术的广度和深度上进行拓展“我们希望用5年的时间,打造上百个高含金量的项目,覆盖主流的32个行业。”传智播客课程研发总监于洋表示。




黑马程序员热门视频教程

Python入门教程完整版(懂中文就能学会) 零起点打开Java世界的大门
C++| 匠心之作 从0到1入门学编程 PHP|零基础入门开发者编程核心技术
Web前端入门教程_Web前端html+css+JavaScript 软件测试入门到精通


在线咨询 我要报名
和我们在线交谈!