C示例
bb.c:
#include "bb.h"
#include <stdio.h>
void bb() {
printf("aa()...n");
aa();
}
c:
#include "aa.h"
#include "bb.h"
int main(int argc, const char** argv) {
aa();
bb();
return 0;
}
aa.h:
#ifndef aa_h
#define aa_h
#include <stdio.h>
void aa() {
printf("aa()...n");
}
#endif // aa_h
bb.h:
#ifndef bb_h
#define bb_h
#include "aa.h"
void bb();
#endif // bb_h
结果C 用clang main.c编译
duplicate symbol _aa in:
/var/folders/f2/2w4c0_n519g8cd2k6xv66hc80000gn/T/main-OsFJVB.o
/var/folders/f2/2w4c0_n519g8cd2k6xv66hc80000gn/T/bb-OkcMzn.o
ld: 1 duplicate symbol for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
c++示例b.cpp:
#include "b.hpp"
void b::do_something_else() {
std::cout << "b::do_something_else() being called..." << std::endl;
a a;
a.doit();
}
main.cpp:
#include "a.hpp"
#include "b.hpp"
int main() {
a a;
b b;
a.doit();
b.do_something_else();
return 0;
}
a.hpp:
#ifndef a_hpp
#define a_hpp
#include <iostream>
class a{
public:
void doit() {
std::cout << "a::doit() being called..." << std::endl;
}
};
#endif // a_hpp
b.hpp:
#ifndef b_hpp
#define b_hpp
#include "a.hpp"
#include <iostream>
class b{
public:
void do_something_else();
};
#endif // b_hpp
c++结果上面的代码在clang++ main.cpp b.cpp
下可以很好地编译,程序的输出为:
a::doit() being called...
b::do_something_else() being called...
a::doit() being called...
为什么在c++版本中出现重复错误not ?
函数
void a::doit()
是在头文件中定义的而不是源文件,这是否意味着编译器将自动内联该函数?
在c++中,类方法不是顶级符号,而是在其类层次结构中有效地限定作用域的名称。
这意味着你已经在c++中定义了两个doit()
方法,a::doit()
和b::doit()
在C语言中,你试图定义一个aa()
函数两次。
doit()
方法, c++也会给出错误。
#include <iostream>
class a {
public:
void doit() {
std::cout << "hello" << std::endl;
}
void doit() {
std::cout << "goodbye" << std::endl;
}
};
导致
ed.cpp:11:8: error: ‘void a::doit()’ cannot be overloaded
void doit() {
^
ed.cpp:7:8: error: with ‘void a::doit()’
void doit() {
^
在您的C
示例中,aa
被定义了两次,这违反了"一次定义规则"。如果它是C++
,这也同样成立。
在C++
的例子中,a::doit
被定义了两次,但是它被隐式地声明为inline
。根据[dcl.fct.spec]/3
,在类中定义的成员函数是隐式内联的:
在类定义内定义的函数是内联函数. ...
inline
函数是每个[basic.def.odr]/5
的一个定义规则(实际上,这是标准要求的inline
的唯一含义)的例外。
可以有一个以上的…带有外部链接的内联函数(7.1.2)…在一个程序中,如果每个定义出现在不同的翻译单元中,并且提供定义满足以下要求. ...
需求本质上归结为一个需求,即定义在它们出现的每个翻译单元中都是相同的。
如果您将aa
声明为inline
,则将应用类似的规则,并且您的代码将按照预期编译和工作。
为什么c++版本不会出现重复错误?
因为没有重复。c++成员函数的作用域由定义它们的类决定。B::doit()不是a::doit()的副本。
函数void a::doit()是在头文件而不是源文件中定义的,这是否意味着编译器将自动内联该函数?