为什么在类中定义的c++成员函数不会产生重复的符号,而在C中却会
Why do C++ member functions defined in a class not produce duplicate symbols, whereas they do in C?
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()是在头文件而不是源文件中定义的,这是否意味着编译器将自动内联该函数?
- 为什么随机数生成器不在void函数中随机化数字,而在main函数中随机化
- 为什么在C的循环中使用printf的Rust代码不显示输出,而在C++的循环中显示std::cout
- 为什么在引用指针时将 const 放在 & 符号的左侧有效,而在右侧则无效?
- 为什么我们需要在 C++ 中检查空指针,而在 Java 中不需要?
- 为什么 'std::reference_wrapper' 在 c++17 中被弃用,而在 c++20 中被删除?
- 在for循环的某些迭代中,字符串的长度为0,而在其他迭代中则不为0
- 为什么带lcov的codecov在Travis上不能正常工作,而在我当地的Linux Mint上却不能正常工作
- dynamic_cast什么时候会因为隐藏符号而失败?
- C++写奇怪的符号而不是字符
- C++11 无符号字符在使用运算符 = 时变为 int
- 为什么在一个地方需要双倍英镑,而在这个宏观上不需要其他地方?
- 为什么在定义类之前声明类的对象会在友元类中给出错误,而在友元函数中不会出错
- 是否有 GCC 警告,用于使用 C 库中的符号而不是通过命名空间 std?
- 为什么我的C 代码在Linux上运行,而在Windows上不运行,是否有RAM内存的问题
- 我的代码在发布模式下不起作用,而在Qt的调试模式下工作
- 如何在字符串C++中添加任何符号而不是另一个符号
- 在 C++ STL 的比较函数中使用"<="符号而不是"<"符号有什么区别?
- 为什么在32位系统上std::size_t是4字节,而在32位和64位系统上无符号长整型都是8字节
- 在c++中,打印数组显示的是符号而不是字符
- 为什么在类中定义的c++成员函数不会产生重复的符号,而在C中却会