标签: C++

26 篇文章

01. 深入学习C++语言先要练好的内功
本文介绍了进程的虚拟地址空间和函数调用时的栈变化。首先,讨论了x86架构下32位程序的虚拟地址空间结构,包括代码段、数据段(`.rodata`​、`.data`​、`.bss`​)、堆和栈的布局。接着,通过一个简单的C++程序示例,展示了函数调用过程中栈的变化。文章详细描述了汇编代码中栈帧的创建、参数传递、局部变量的存储以及返回值的处理过程。最后,强调了虚拟地址空间和虚拟内存的区别与联系,指出虚拟地址空间是逻辑上的概念,而虚拟内存是实现虚拟地址空间和物理内存交互的底层技术。
26. 实例化
模板实例化是C++中从模板定义生成实际代码的过程。编译器在需要使用模板类或函数的实际定义时进行实例化。实例化一个模板类并不意味着要实例化其所有成员函数。C++提供了显式实例化和`extern template`关键字来帮助用户控制模板的实例化,优化编译和链接过程,并消除名字绑定带来的意外。 名字绑定是指在模板实例化时,编译器找到模板中使用的所有名字的定义。依赖名字的查找会延迟到实例化时进行,而非依赖名字在模板定义时即已完成绑定。默认情况下,编译器假定依赖名字不是类型名,除非用`typename`显式说明。类似地,引用成员模板时需使用`template`关键字。 通过理解模板实例化和名字绑定的机制,程序员可以更有效地控制和优化模板代码的生成和使用。
25. 特例化
本文介绍了C++模板参数的三种类型:类型参数、值参数和操作参数。 1. **类型参数**:使用`typename`或`class`关键字定义,可以是任何类型,无约束。类型参数在模板内部无额外空间开销,且必须是作用域内且可访问的。 2. **值参数**:非类型或模板的模板参数,传递给它的实参成为值参数。值参数可以是整型常量表达式、指向外部链接的对象或函数的指针或引用、指向非重载成员指针、`nullptr`指针。C++不允许浮点数和字符串字面量作为模板值参数。值参数在模板内部是常量,不可修改。 3. **操作参数**:用于指定比较准则等操作。C++标准库中的`map`容器允许用户自定义比较准则。可以通过模板值参数传递比较函数指针,或通过类型参数传递比较对象类型。使用类型参数更灵活,因为可以传递任意类型的函数对象,而不仅仅是函数指针。函数对象可以携带状态,比简单函数指针更灵活。 总结来说,C++模板参数提供了高度的灵活性和通用性,允许开发者根据需要定制类型、常量值和操作。
24. 泛型程序设计
本文介绍了C++模板编程的主要用途和特性,包括传递类型参数、类型检查和推断、以及编译时多态。模板支持泛型程序设计,使得算法可以适应多种数据类型,同时避免了运行时开销和类型不兼容错误。此外,文章还探讨了具体化概念在模板中的应用,通过谓词函数和编译期检查来定义类型的约束条件。公理作为一种无法证明但被认为正确的特性,用于简化模板设计,例如表示赋值操作后的值相等性等。总体而言,C++模板编程提供了强大的工具,使程序设计更加通用和高效。
23. 模板
本文介绍了C++中的字符串模板类 `String`,它通过模板参数 `C` 支持不同字符类型的字符串。文章首先展示了 `String` 类的定义,并解释了如何使用模板参数来创建具体类型的字符串对象,如 `String` 和 `String`。 接着,文章讨论了模板实例化的概念,即编译器根据模板和模板参数生成具体的类或函数。模板实例化可以减少代码冗余,提高代码复用性,但也会生成大量几乎相同的函数。 文章还提到了类型检查的问题,指出C++无法直接表达对模板参数的约束要求。例如,无法直接要求模板参数必须是某种容器类型,并且其元素类型必须能与另一个类型进行比较。 最后,文章强调了类型等价的概念,即使用相同模板实参生成的类型应该是等价的。例如,`String` 和 `String` 是等价的,因为它们都是 `unsigned char` 的别名。 总的来说,本文详细介绍了C++模板的定义、实例化过程以及类型检查和等价性的相关问题,帮助读者理解如何利用模板实现类型无关的通用代码。
22. 运行时类型信息
22. 运行时类型信息 类层次导航 在软件开发中,尤其是在图形用户界面(GUI)编程中,经常需要在系统(如 GUI 库和操作系统)与应用程序之间传递对象。这些对象通常被称为小部件(widget)或控件(control)。由于系统不了解应用程序中对象的具体细节,类型信息在传递过程中可能会丢失。为了恢复这些丢失的类型信息,我们需要一种机制来在运行时检测…
21. 类层次
多重继承 多重继承是一种面向对象编程的特性,它允许一个类从多个基类继承属性和方法。这种继承方式提供了两种主要好处: 共享接口(Shared Interface) :通过继承,可以减少重复代码,统一代码规范。这种方式通常被称为运行时多态(Run-time Polymorphism)或接口继承(Interface Inheritance)。 共享实现(…
20. 派生类
派生类 在面向对象编程中,派生类(子类)与基类(超类)之间存在一种继承关系。派生类通过继承机制获得基类的属性和方法。这种关系可以用一个箭头图表示,箭头从派生类指向基类,表示派生类引用基类。 ​​ 成员函数 在面向对象编程中,继承允许派生类继承并扩展基类的功能。派生类可以定义自己的成员函数,这些函数可以调用基类的公有和保护成员,但不能访问基类的私有成…
19. 特殊运算符
特殊运算符 在 C++ 中,有一些特殊运算符,如 ++​、--​、new​、delete ​等,它们与传统的一元或二元运算符(例如 +​、<​、~​)有所不同。这些特殊运算符在使用时,从代码中的使用到程序员定义的映射与传统运算符有轻微的差别。其中,取下标([]​)和函数调用(()​)是两种最重要的用户自定义运算符。 取下标运算符([]​) 通…
18. 运算符重载
引言 C++ 允许用户为自定义类型重载运算符,以实现类似于内置类型的操作。 class complex { double re, im; public: complex(double r, double i) : re(r), im(i) {} complex operator+(const complex& other); complex…