昨天在公司干活的时候遇到一个C++隐式转换的问题, 折腾了很久, 后来碰巧发现了一丝线索, 才得以解决. 废话不多说了, 先上代码:
// 此数组模板类声明
template
class SomeArray {
SomeArray(int physicalLength = 32, int growLength = 32);
...
int append(const T& value);
AcArray& append(const AcArray& otherArray);
...
};
// 枚举类型
enum Format { kFirst, ..., kLast };
// 问题代码
SOME_FUNC(...) {
...
SomeArray<Format> fmtArray;
...
for (int fmt = kFirst; fmt <= kLast; ++fmt) {
if (fmt satisfy some condition) fmtArray.append(fmt);
}
}
上述问题代码在执行循环的时候, 明明append元素这条语句执行了, 但是fmtArray仍然为空. 于是我就在这条语句处设置 了断点, 然后F11进去看. 结果发现跳转到了SomeArray的构造函数里. 然后我又尝试了几次, 发现还是如此. 我就纳闷, 难道我构建出来的二进制出错导致link不对? 不可能啊, 这是一个模板类, 不需要link啊. 又或者是因为这个模板类是编译在一个pch文件里, 那个文件被弄dirty了? 尝试了一下, 发现不是由于link或者pch导致的. 没办法了, 下班前, 开始做了一个fully clean build(2 ~ 3小时), 希望排除某些模块的dirty所导致的问题.
今天上班后, 和同事J继续调试, 发现, 居然还是继续跳入构造函数. 构造函数调用完毕后, 退回到append元素语句处. 这时候奇迹发生了: 同事J手一不小心, 又按了一下F11, 结果, 居然跳入了append函数内部. 这个append函数并不是append一个元素, 而是一个SomeArray<Format> 对象, 但是这个对象是空的. 执行完毕这个函数后, 继续按F11, 结果跳到了SomeArray的析构函数. 到这里, 问题基本上已经很清楚了:
由于fmt是一个整形值, 那么C++在解析重载append函数时, 由于Integer->Enumeration的转换不能自动进行, 所以编译器倾向于寻找一条更可行的转换链: int -> SomeArray<Format>, 因为默认构造函数支持这种转换. 于是, 你所append的每个元素, 都用来作为构建临时数组对象时所使用的physicalLength 参数值. 最终得到的fmtArray也因为append了一堆空数组而始终为空.
从这个问题, 我得到两个结论:
1. C++的类型转换的确诡异, 自己平时编写的时候, 一定要注意适当地使用explicit关键字,避免不必要的隐式转换.
2. 遇到诡异的事情, 还是要沉着冷静, 利用已有的信息去进行深入的分析, 不放过每个可疑的线索.
分享到:
相关推荐
C++隐式转换问题分析及解决办法 C++隐式转换问题是编程中常见的问题之一,了解隐式转换的原理和规则对于编写高效、安全的代码至关重要。本文将对C++隐式转换问题进行分析,并提供解决办法。 隐式转换的定义 ------...
编译器经常会背着我们做一些我们不希望发生的事情,典型的是隐式转换。不过庆幸的是,编译器只会帮助我们进行一次转换,而不会无休止的隐式转换,直至满足条件为止。例如,下面先定义一个Array模板类: template...
c++,隐式转换及explicit简单介绍,个人(新人)分享,有误请勿喷。
在`main`函数中,`Date`对象`now`被隐式转换为`int`类型,并存储在变量`since`中,随后输出。 除了上述两种类型转换,还可以定义类之间的转换函数,允许不同自定义类的对象互相转换。例如,可以创建一个`CustomDate...
C++可以定义如何将其他类型的对象隐式转换为我们的类类型或将我们的类类型的对象隐式转换为其他类型。为了定义到类类型的隐式转换,需要定义合适的构造函数。 说明:可以用单个实参来调用的构造函数定义了从形参...
因此,开发者应当谨慎使用,并在必要时使用 `explicit` 关键字来禁止某些构造函数的隐式转换,以提高代码的可读性和安全性。例如,如果 `People` 类的构造函数被声明为 `explicit`,那么像 `People::addToVector(...
C++从C发展而来,也继承两种C风格的转换:隐式转换和显式转换。 1.隐式转换 隐式转换是指由编译系统自动进行,不需要人工干预的类型转换,例如: short a = 2000; int b; b = a; 隐式转换,也包括构造函数和...
C++隐式类型转换运算符operator type()用法详解 C++隐式类型转换运算符operator type()是一种特殊的成员函数,用于实现类型转换的自动转换。这种运算符可以将一个类对象转换为其他类型,例如基本数据类型、自定义类...
在C++编程中,类的隐式转换和强制转换是两个关键的概念,它们允许程序员在不同数据类型之间灵活地转换。隐式转换是编译器自动进行的转换,而强制转换则是程序员通过特定语法明确指示的转换。 首先,让我们探讨隐式...
C++提供了多种方式进行类型转换,包括隐式转换和显式转换。本篇内容将详细解析C++中的类型转换机制,并结合《C++必知必会》这本书中的知识点进行深入探讨。 首先,我们来看C++的隐式类型转换。隐式转换是指编译器...
本篇文章将深入探讨C++中的数据类型转换,包括隐式转换和显式转换,并通过实例来解释它们的用法。 ### 隐式类型转换(Automatic Type Conversion) 隐式类型转换是指在某些操作或赋值过程中,编译器自动进行的数据...
本资源包,"C++class_convert.rar",主要关注C++中的类型转换,包括隐式转换和显式转换,这对于理解和编写高效、安全的代码至关重要。 1. **隐式类型转换(自动类型转换)**:这是编译器自动执行的转换,当一个类型...
本篇文章将深入探讨C++中不同类型的转换方法,包括隐式转换和显式转换,以及它们在实际编程中的应用。 首先,我们讨论隐式类型转换(也称为自动类型转换)。在C++中,当一个数据类型可以安全地被转换为另一种类型时...
综上所述,“C++类型转换大全”涵盖了C++中主要的类型转换方法,包括隐式转换和显式转换的各种形式,以及它们在实际编程中的应用和注意事项。通过深入学习和实践这些内容,开发者可以更加灵活地控制和管理程序中的...
在C#中,数据类型的转换可以通过显式转换(CType、Convert类、(Type))或隐式转换进行。例如,从int转换到double可以使用隐式转换,而从object转换到具体类型则需要显式转换。在处理时间戳时,C#提供了DateTime结构...
### C++类型转换详解 #### 一、引言 在C++编程中,类型转换是一项基本而重要的功能,它允许开发者将一个类型的变量或表达式转换为另一个类型的变量或表达式。良好的类型转换机制能够帮助程序员更好地管理数据类型...
有时候,我们并不希望发生隐式转换,不期望的隐式转换可能出现意外的结果。explicit关键词可以禁止类隐式转换。 例如: ```cpp class A { public: A(int a) : num(a) {} explicit A(B b) : num(b.num) {} ~A() ...