C++为什么覆盖全局new操作符和类特定操作符不会产生歧义?
下面一节讨论重载决议,因为它有助于重载和覆盖的基础知识。
预测输出:
编译器如何区分类特定函数和全局函数? 为了将函数调用与相应的函数定义进行映射,编译器执行名称查找过程。这个过程产生了一些具有相同名称的函数,它们被称为候选函数。如果有多个候选函数,则编译器执行参数相关的查找过程。如果这个过程也产生多个候选函数,则进行重载决议过程,选择要调用的函数。如果任何一个候选函数是相应类的成员函数(静态或非静态),则它会被预设一个隐式对象参数,该参数代表它们被调用的对象,并出现在实际参数的第一个之前。
预测输出:
这就是运算符重载的重载决议工作原理: 对于一元和二元运算符,候选函数的选择来自不同的作用域。它们是:1)成员候选函数:在类中定义的重载运算符函数。2)非成员候选函数:在全局定义的重载运算符函数。3)内置候选函数:执行指定操作的内置函数。因此,在上面的程序中,在编译期间,候选函数的数量大于1,同时 所有这些候选函数具有相同的优先级 ,因此会产生歧义的重载错误。
预测输出:
输出:
程序之所以能正常运行的原因是: C++标准规定,“如果一个类具有类特定的分配函数,则调用该函数,而不是全局的分配函数。 这是有意的:类成员应该最了解如何处理该类”。这意味着,当new表达式寻找相应的分配函数时,它从类作用域开始,然后检查全局作用域,如果提供了类特定的新分配函数,则调用它。否则,它将检查全局范围并调用它。如果全局范围中不存在new函数,则会调用内置的new函数。因此,在上面的示例中, 候选函数的优先级不同 ,因此可以编译而不出现任何错误。 程序员是否可以在定义了类特定new运算符的情况下调用全局new操作符? 是的。C++为此提供了作用域解析运算符。如果new运算符前面带有作用域分辨率(::)运算符,则编译器会在全局作用域中搜索operator new。 如果未在全局作用域中定义new运算符,并且您正在使用::单目运算符调用new运算符会发生什么? 编译器将调用内置的new函数。下面的示例演示了其工作原理。它确实包含类特定的new运算符,但是全局运算符new。因此,在调用::new时,编译器会调用标准库new函数。 C++为什么提供了这种新函数的可扩展性?
- 性能: 内置的内存分配器函数是通用型函数,适用于预定义的数据类型。对于具有非常特定数据需要分配的用户定义数据类型,通过定制它们被分配的方式,可以大大加快内存管理的速度。
- 调试和统计: 对内存使用方式的控制为调试、统计和性能分析提供了极大的灵活性。