The meaning of C++ declaration and definition, internal linkage and external linkage

1. Declaration and Definition

A. In most cases, a declaration is the same as a definition, but there are rare cases where a declaration is not a definition, and a definition is not a declaration:
1. It is a declaration, but it is not a definition:

1) 声明了一个没有具体说明函数体的函数; void declaration(int a,int b);
2) 包含了一个extern说明符,并没有初始化或函数体;Extern int number;
3) 它是一个类定义内的静态类数据成员的声明; class test{...; static int a; ...};
4) 它是一个类名的声明; class A;
5) 它是一个typedef声明; tepedef int INT;

2. It is a definition, but not a statement:

1) 定义了一个静态类数据成员;  int test::a = 4 或者 static int a=42) 定义了一个non-inline成员函数; void declaration(int a,int b){return (a<b?a:b)}

B. A declaration introduces a name into a program, and a definition provides a unique description of an entity (eg, type, instance, function) within a program
In C++, a declaration differs from a definition in that: within a given It is legal to repeat a declaration in the scope. Most declarations can be repeated, but definitions can only be repeated once.

Repeat multiple times:

void declaration(int a,int b);
void declaration(int a,int b);
class A;
class A;
typedef int INT;
typedef int INT;
friend IntSetIter;
friend IntSetIter;
extern int number;
extern int number;

The above are all declarations and can be repeated multiple times within a single scope. On the other hand, the following declarations at file scope are also definitions, and therefore cannot appear more than once in a given scope, otherwise a compilation error will be raised:

int x;
char *p;
Extern int number=1;
static int number;
static int f(int. int) {/* ... */}
inline int h(int. int) {/* ... */}
enum color{RED,GREEN,BLUE}   //只要是枚举的其实只能重复一次
const double DEFAULT_TOLERANCE = 1.0e-6
class stack{/*...*/}
union Rep {/*...*/}

Function and static data member declarations are exceptions. Although they are not defined, they cannot be repeatedly defined in a class definition:

class NoGood{
        static int i; //declaration
        static int i; // illegal in C++
    public:
        int f(); //declaration
        int f(); //illegal in C++
}

2. Internal and external links

When compiling a .c file, the C Pre-Processor (CPP) first includes the header files recursively, forming a single source file that contains all the necessary information. After that, compile this intermediate file (called the compile file) to generate a .o file (object file) with the same name as the root file.

The linker links symbols generated by various compilation units to generate an executable program. There are two different kinds of links: internal links and external links. The link type directly affects how we incorporate a given logical structure into the physical design.

(In simple terms, there are two steps: 1. Generate the root file (test.cpp) and the .o file (test.o) for each compilation unit, 2. Link various symbols through the linker to generate executable files)

1) Internally linked definition: Internally linked means that access to this definition is restricted by the current compilation unit. That is, a definition with internal linkage is not visible to any other compilation unit. E.g:

static int x;
enum Boolean{No, Yes};

Specifically:

1. Definition of static (static) global variable, definition of static free function, definition of static friend function
2. Definition of class
3. Definition of inline function 4. Definition of
Union community 5. Definition
of const constant
6. Definition of enumeration type
7. All Statements

An important example of a definition with internal linkage is the definition of a class. A class description (below) is a definition. Therefore, it cannot be defined repeatedly within a compilation unit of the same scope. Classes used outside a single compilation unit must be defined in a header file.

class Point{
    int d_x;
    int d_y;
  public:
     Point(int x,int y):d_x(x),d_y(y){}   //internal linkage
     int x() const{return d_x;}   //internal linkage
     int y() const{return d_y;}   //internal linkage
};

inline int ..() {};  //internal linkage

2) External linkage definition: External linkage means that the definition is not limited to a single compilation unit. In .o files, definitions with external linkage produce external symbols that are accessible by all other compilation units to resolve symbols that are not defined in other compilation units.
Specifically:

1. Definition of class non-inline functions (including member functions and static class member functions)
2. Definition of class static member variables
3. Namespace or global non-static free functions, non-static variables, non-friend functions Definition

There are entities represented by some name definitions that have external linkage, which means that they can link code across compilation units.

Therefore, if an entity with external linkage is declared in a header file and is included by multiple .cpp files, a link conflict error may occur, because each .cpp that contains this externally linked entity will allocate space. When multiple compilations When the unit is linked, the connector will face multiple identical names and cannot link to the correct object normally.

//math.h

namespace lesson_n
{
    int test_n;
}
class lesson_c
{
    int test_c
}
//main.cpp

#include "lesson.h"
int _tmain(intargc,_TCHAR*argv[])
{
         system("pause");
         return0;

}
//math.cpp

#include "lesson.h"
CMakeFiles/chess.dir/main.cpp.o:(.bss+0x4): multiple definition of `lesson_n::test_n'
CMakeFiles/chess.dir/math.cpp.o:(.bss+0x0): first defined here

It is found that the test defined by the namespace reports an error, while the test defined by the class does not report an error. This is because namespace defines external linkage, and class defines internal linkage, and the compiler treats it as a private copy of each compilation unit.

Finally, give a C++ programming suggestion, carefully consider defining linked entities in the header file

First, if the header file is defined like int a=1;, it will definitely report a link error after being included in multiple .cpp files.

Second, if you want to static int a = 2; such a definition will generate a copy in all the .cpp files that include it. If it is included by a large number of source files, it will occupy a lot of space and cause memory waste.

refer to:大规模C++ 程序设计/(美) 洛科什 (Lakos. J.)著; 刘冰,张林译. —北京: 机械工业出版社,2014.8

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325602236&siteId=291194637