C - 一个函数声明,多个定义,并且仍然有效
C++ - One Function Declaration, Multiple definitions, And it still works?
好吧,我有3个文件,一个标头,所述标头的来源和一个主。在标题文件中,我定义具有功能的类。在源文件中,我定义该函数。但是,在主文件中,i 重新定义该函数,然后在主函数中进行类的实例并调用函数。这可以很好地编译 - 没有任何警告。至少可以说,输出很可怕。
标题:testme.h
#ifndef testme_h_
#include <iostream>
using namespace std;
class wtf {
public:
string getStr();
};
#endif
来源:testme.cpp
#include "testme.h"
string wtf::getStr() {
return "Hello World!";
};
main:main.cpp
#include <iostream>
using namespace std;
#include "testme.h"
string wtf::getStr()
{
return "God is Dead.";
}
int main()
{
wtf f;
cout << f.getStr() << endl;
}
输出:
God is Dead.
为什么这起作用?为什么关于多个定义没有错误?为什么souce文件的定义被忽略了?为什么没有警告?
部分答案当将其重新编译为" g main.cpp testme.cpp -o sanity.o",实际上确实会产生链接器错误。
让我得到的,但是,我写了一个镜像我在库中定义一个函数的镜像的小案例,但是我们在另一个"测试套件"程序中重新定义了一个函数方式。为什么这样?在图书馆中它允许它覆盖ODR?
为什么这起作用?为什么关于多个定义没有错误?为什么souce文件的定义被忽略了?为什么没有警告?
部分答案是在将其重新编译为" g main.cpp testme.cpp -o sanity.o"时。实际上,它确实会产生链接器错误。
在C 的设计和演变中,Stroustrup说,在设计功能时,他偶尔会在(1((1(复杂规则之间进行选择,即编译器能够使用警告和错误消息执行,或(2(一个简单的规则,即编译器在所有情况下都无法执行。他试图选择简单的规则,他希望编译器最终能够执行/检测错误。C和C 的几个部分有效地显示了1970年代,1980年代,1990年代等的最新状态(例如inline
,register
,volatile
(。可能还有更多。
大致来说,这种权衡是标准中未定义行为的来源。如果不能执行一个简单的规则(或委员会认为执行该规则很昂贵(,则该规则停留在标准中,违反行为是不确定的。从不触发未定义的行为是程序员的责任。编译器和相关工具有可能在某些时候执行其中一些规则。某些编译器或相关工具甚至可能始终执行其中的某些规则。但是,总的来说,您是一个人。
设计和进化甚至包括对您的特定问题的讨论。编写编译器后,Stroustrup也不想写一个链接器。他想出了一种简单的方法来依靠系统链接器,但是在早期,许多连接器对符号可能长时间有严格的限制。他努力说服那些编写系统接头的人,以使他们与Cfront一起工作。最终,他成功了。
今天,链接器通常带有编译器,但是标准委员会仍然将其视为单独的工具,可能在编写编译器的人们的控制之外。一个定义规则的存在很大程度上是为了确保编译器的输出与大多数标准链接器兼容,但是委员会不需要这些链接者能够检测到违反ODR的行为。此外,可以逐步编译和链接程序,因此无法保证链接器将有足够的信息来检测违反ODR的行为。
值得注意的是,许多编译器将为inline
功能和template
函数生成多个符号,希望链接器抛出冗余定义。因此,链接器不一定要查看多个定义是错误的。(就ODR而言,这些定义必须相同,以便链接器可以扔掉所有的定义。(
在库中它允许它覆盖ODR?
我不会说"覆盖"。听起来这种行为是故意的。我会说"违反未被发现的违法"。答案只是"标准委员会不期望链接者始终发现违规行为,而且许多链接者都不会。"避免违规是您的责任。但是,您不是一个人:一部分名称空间是为了使这个问题更容易解决。
- 自定义先决条件对移动分配运算符有效吗
- C++ 返回指向函数内定义的静态数组的指针是否有效?
- 此递归模板类型定义是否有效C++?
- 错误 - 自定义数据类型作为有效负载,带有提升::几何
- 自定义类型转换运算符在转发引用上调用时不起作用(当对象按值传递时有效)
- 通过自定义分配器和删除器有效使用shared_ptr
- 当程序从该函数调谐器时,指向在函数中声明和定义的某些 C 字符串的指针不再有效.为什么?
- 如何确定以浮点数、双精度位数为单位的有效宽度:是否有标准定义?
- C - 一个函数声明,多个定义,并且仍然有效
- 静态常量声明,变量的constexpr定义,有效的c ++?
- 将流定义为私有类变量似乎在Linux下有效,但在WindowsVisualStudio下无效
- 未解析的外部符号错误,仅在标头中定义函数时有效
- 为什么仅在返回通用类中的自定义类型时才有效constexpr成员函数
- 是无定义的类声明,有效为模板参数
- std::unique_ptr的自定义deleter是手动调用析构函数的有效位置吗
- 为什么在头文件中定义类是有效的,而不是函数
- 在枚举类上使用“reinterpret_cast” - 有效或未定义的行为
- STL 集自定义排序函数在 Qunicy 2005 中有效,但在 MS Studio 2010 中不起作用
- GoogleTest仅在定义在.h文件中时才有效
- 定义内省C++类层次结构描述的有效方法