• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >C语言 > 完全掌握C++编程中构造函数使用的超级学习教程

完全掌握C++编程中构造函数使用的超级学习教程

作者: 字体:[增加 减小] 来源:互联网 时间:2017-05-28

通过本文主要向大家介绍了完全掌握C++编程中构造函数使用的超级学习教程等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

构造函数是一种可初始化其类的实例的成员函数。构造函数具有与类相同的名称,没有返回值。构造函数可以具有任意数量的参数,类可以具有任意数量的重载构造函数。构造函数可以具有任何可访问性(公共、受保护或私有)。如果未定义任何构造函数,则编译器会生成不采用任何参数的默认构造函数;可以通过将默认构造函数声明为已删除来重写此行为。
构造函数顺序
构造函数按此顺序执行工作:
按声明顺序调用基类和成员构造函数。
如果类派生自虚拟基类,则会将对象的虚拟基指针初始化。
如果类具有或继承了虚函数,则会将对象的虚函数指针初始化。虚函数指针指向类中的虚函数表,确保虚函数正确地调用绑定代码。
它执行自己函数体中的所有代码。
下面的示例显示,在派生类的构造函数中,基类和成员构造函数的调用顺序。首先,调用基构造函数,然后按照基类成员在类声明中出现的顺序对这些成员进行初始化,然后,调用派生构造函数。

#include <iostream>
using namespace std;

class Contained1 {
public:
  Contained1() {
    cout << "Contained1 constructor." << endl;
  }
};

class Contained2 {
public:
  Contained2() {
    cout << "Contained2 constructor." << endl;
  }
};

class Contained3 {
public:
  Contained3() {
    cout << "Contained3 constructor." << endl;
  }
};

class BaseContainer {
public:
  BaseContainer() {
    cout << "BaseContainer constructor." << endl;
  }
private:
  Contained1 c1;
  Contained2 c2;
};

class DerivedContainer : public BaseContainer {
public:
  DerivedContainer() : BaseContainer() {
    cout << "DerivedContainer constructor." << endl;
  }
private:
  Contained3 c3;
};

int main() {
  DerivedContainer dc;
  int x = 3;
}

</div>

这是输出:

Contained1 constructor.
Contained2 constructor.
BaseContainer constructor.
Contained3 constructor.
DerivedContainer constructor.
</div>

如果构造函数引发异常,析构的顺序与构造的顺序相反:
构造函数主体中的代码将展开。
基类和成员对象将被销毁,顺序与声明顺序相反。
如果是非委托构造函数,所有完全构造的基类对象和成员均将被销毁。但是,对象本身不是完全构造的,因此析构函数不会运行。
成员列表
使用成员初始值设定项列表从构造函数参数初始化类成员。此方法使用直接初始化,这比在构造函数体内使用赋值运算符更高效。

class Box {
public:
  Box(int width, int length, int height) 
    : m_width(width), m_length(length), m_height(height) // member init list
  {}
  int Volume() {return m_width * m_length * m_height; }
private:
  int m_width;
  int m_length;
  int m_height;

};

</div>

创建 Box 对象:

Box b(42, 21, 12);
cout << "The volume is " << b.Volume();
</div>

显式构造函数
如果类具有带一个参数的构造函数,或是如果除了一个参数之外的所有参数都具有默认值,则参数类型可以隐式转换为类类型。例如,如果 Box 类具有一个类似于下面这样的构造函数:

Box(int size): m_width(size), m_length(size), m_height(size){}
</div>

可以初始化 Box,如下所示:

Box b = 42;
</div>

或将一个 int 传递给采用 Box 的函数:

class ShippingOrder
{
public:
  ShippingOrder(Box b, double postage) : m_box(b), m_postage(postage){}

private:
  Box m_box;
  double m_postage;
}
//elsewhere...
  ShippingOrder so(42, 10.8);

</div>


这类转换可能在某些情况下很有用,但更常见的是,它们可能会导致代码中发生细微但严重的错误。作为一般规则,应对构造函数使用 explicit 关键字(和用户定义的运算符)以防止出现这种隐式类型转换:

explicit Box(int size): m_width(size), m_length(size), m_height(size){}
</div>

构造函数是显式函数时,此行会导致编译器错误:ShippingOrder so(42, 10.8);。
默认构造函数
默认构造函数没有参数;它们遵循略有不同的规则:
默认构造函数是一个特殊成员函数;如果没有在类中声明构造函数,则编译器会提供默认构造函数:

class Box {
  Box(int width, int length, int height) 
    : m_width(width), m_length(length), m_height(height){}
};

int main(){

  Box box1{}; // call compiler-generated default ctor
  Box box2;  // call compiler-generated default ctor
}

</div>

当你调用默认构造函数并尝试使用括号时,系统将发出警告:

class myclass{};
int main(){
myclass mc();   // warning C4930: prototyped function not called (was a variable definition intended?)
}
</div>

这是“最棘手的解析”问题的示例。这种示例表达式既可以解释为函数的声明,也可以解释为对默认构造函数的调用,而且 C++ 分析器更偏向于声明,因此表达式会被视为函数声明。
如果声明了任何非默认构造函数,编译器不会提供默认构造函数:

class Box {
  Box(int width, int length, int height) 
    : m_width(width), m_length(length), m_height(height){}
};
private:
  int m_width;
  int m_length;
  int m_height;

};

int main(){

  Box box1(1, 2, 3);
  Box box2{ 2, 3, 4 };
  Box box4;   // compiler error C2512: no appropriate default constructor available
}

</div>

如果类没有默认构造函数,将无法通过单独使用方括号语法来构造该类的对象数组。例如,在前面提到的代码块中,框的数组无法进行如下声明:

Box boxes[3];  // compiler error C2512: no appropriate default constructor available

</div>

但是,你可以使用初始值设定项列表将框的数组初始化:

Box boxes[3]{ { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };
</div>

复制和移动构造函数
复制构造函数是特殊成员函数,它采用对相同类型对象的引用作为输入,并创建它的副本。移动也是特殊成员函数构造函数,它将现有对象的所有权移交给新变量,而不复制原始数据。

显式默认构造函数和已删除构造函数
你可以显式设置默认复制构造函数、设置默认构造函数、移动构造函数、复制赋值运算符、移动赋值运算符和析构函数。你可以显式删除所有特殊成员函数。
派生类中的构造函数
派生类构造函数始终调用基类构造函数,因此,在完成任何额外任务之前,它可以依赖于完全构造的基类。调用基类构造函数进行派生,例如,如果 ClassA 派生自 ClassB,ClassB 派生自 ClassC,那么首先调用 ClassC 构造函数,然后调用 ClassB 构造函数,最后调用 ClassA 构造函数。
如果基类没有默认构造函数,则必须在派生类构造函数中提供基类构造函数参数:

class Box {
public:
  Box(int width, int length, int height){
    m_width = width;
    m_length = length;
    m_height = height;
  }

private:
  int m_width;
  int m_length;
  int m_height;
};

class StorageBox : public Box {
public:
  StorageBox(int width, int length, int height, const string label&) : Box(width, length, height){
    m_label = label;
  }
private:
  string m_label;
};

int main(){

  const string aLabel = "aLabel";
  StorageBox sb(1, 2, 3, aLabel);
} 

</div>

具有多重继承的类的构造函数
如果类从多个基类派生,那么将按照派生类声明中列出的顺序调用基类构造函数:

#include <iostream>
using namespace std;

class BaseClass1 {
public:
  BaseClass1() {
    cout << "BaseClass1 constructor." << endl;
  }
};
class BaseClass2 {
public:
  B



 
分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

相关文章

  • 2017-05-28C语言文件操作函数freopen详细解析
  • 2017-05-28C++ 如何用cout输出hex,oct,dec的解决方法
  • 2017-05-28static_cast,dynamic_cast,reinterpret_cast,const_cast的区别及用法详解
  • 2017-05-28C++中fstream,ifstream及ofstream用法浅析
  • 2017-05-28利用C语言实现2048小游戏的方法
  • 2017-05-28C语言快速幂取模算法小结
  • 2017-05-28C语言中强制地址跳转详解
  • 2017-05-28在Visual Studio使用C++开发Metro应用
  • 2017-05-28给ActiveX签名的实现方法详解
  • 2017-05-28C语言计算代码执行所耗CPU时钟周期

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • 如何判断一个数是否为2的幂次方?若是,并判断出来是多少次方?
    • 详解C语言中getgid()函数和getegid()函数的区别
    • C++中的内存分区介绍
    • C语言JSON查询
    • 详解C++编程中用数组名作函数参数的方法
    • C语言fillpoly函数详解
    • C++ 构造双向链表的实现代码
    • C++并查集亲戚(Relations)算法实例
    • C语言中字符串和数字的相互转换实现代码
    • window调用api列出当前所有进程示例

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有