1

C Example

bb.c:

#include "bb.h"
#include <stdio.h>

void bb() {
    printf("aa()...\n");
    aa();
}

main.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 Result

Compiled with clang main.c bb.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++ Example

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++ Result

The above compiles fine with clang++ main.cpp b.cpp and the output to the program is:

a::doit() being called...
b::do_something_else() being called...
a::doit() being called...

Questions

  1. Why does the duplicate error not occur with the C++ version?

  2. Does the fact that the function void a::doit() is defined in the header file rather than a source file mean that the compiler will automatically inline the function?

4

3 回答 3

2

在 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() {
        ^
于 2014-07-09T03:46:39.000 回答
1

In your C example, aa is defined twice, which violates the "one definition rule". This would be equally true if it were C++.

In your C++ example, a::doit is defined twice, but it is implicitly declared inline. Member functions defined within a class are implicitly inline per [dcl.fct.spec]/3:

A function defined within a class definition is an inline function. ...

inline functions are an exception to the one definition rule (in fact, this is the only meaning of inline required by the standard) per [basic.def.odr]/5.

There can be more than one definition of a ... inline function with external linkage (7.1.2) ... in a program, provided that each definition appears in a different translation unit, and provided the definitions satisfy the following requirements. ...

The requirements essentially boil down to a requirement that the definitions be identical in every translation unit where they appear.

Had you declared aa as inline, similar rules would have applied and your code would have compiled and worked as expected.

于 2014-07-09T05:04:17.503 回答
0

为什么 C++ 版本不会出现重复错误?

因为没有重复。C++ 成员函数的作用域由定义它们的类确定。b::doit() 不是 a::doit() 的副本。

函数 void a::doit() 是在头文件而不是源文件中定义的这一事实是否意味着编译器将自动内联该函数?

不,但这意味着它是可能的。

于 2014-07-09T03:46:46.077 回答