C++程序员应了解的那些事(99)之 C++中的ODR法则
程序员文章站
2022-07-12 22:54:50
...
C++ 标准规定“每个程序应该只包含那个程序中用到的每个非内联函数或对象的一个定义”。然而在同一个程序中,一个类、枚举类型、具有内部链接的内联函数和和一 个模板可能有不止一个定义——只要每个定义出现在一个独立的翻译单元即可。对于内联函数和模板的情况,常用做法是在头文件中编写它们的定义,然后在每个独 立编译的源文件中使用 #include 引入它。
定义的同等性
这就引出一个问题:什么时候两个定义完全相同?单定义规则 (ODR,One Definition Rule)定义了两个或多个定义必须满足完全相同的需求。在不同的翻译单元中,当且仅当两个定义中每个符号都相同,并且这些符号在两个翻译单元具有相同的意思时,这两个定义才完全相同。例如:
//file first.cpp
inline int D::getVal () { return 10; }
//file second.cpp
typedefint I;
inline I D::getVal () { return 10; }
在这个例子中getVal() 的定义看上去似乎相同。然而它们打破了 ODR,因为‘I’和‘int’不是相同的符号,虽然它们的意思一样。
在下面这个例子中,两个定义是逐个符号都相同的,但是它们依然打破了 ODR,因为每个定义中的符号不具有同样的意思:
//file first.cpp
#define I long
inline I D::getVal () { return 10; }
//file second.cpp
typedef int I;
inline I D::getVal () { return 10; }
空格和注释不影响 ODR。在下面的例子中,两个定义在写法上不同的,但是它们依然满足 ODR:
//file first.cpp
inline intC::getVal () { return 10; }
//file second.cpp
inline intC::getVal () { /*complies with the ODR*/
return 10; }
上一篇: android顶部标签栏的实现
推荐阅读
-
程序员应了解的那些事(16)C语言中利用setjmp和longjmp做异常处理 / 不要在C++中使用setjmp和longjmp
-
C++程序员应了解的那些事(64)~ 指向 Data Member 的指针 <成员指针>
-
C++程序员应了解的那些事(68)非类型模板参数
-
C++程序员应了解的那些事(47)函数之 传入传出参数 / 默认参数
-
C++程序员应了解的那些事(36)Effective STL第6条:当心C++编译器中最烦人的分析机制 --- 调用构造函数被误认为是函数声明的问题
-
C++程序员应了解的那些事(63)STL内建函数对象、仿函数
-
C++程序员应了解的那些事(62)~ list::splice()函数详解
-
C++程序员应了解的那些事(94)之STL容器内存释放问题
-
C++程序员应了解的那些事(99)之 C++中的ODR法则
-
C++程序员应了解的那些事(18)C++11 通过key访问map容器:下标访问、at()、find、lower_bound&upper_bound、equal_range