Why One Definition Rule, not One Declaration Rule?

我与影子孤独终老i 提交于 2021-01-27 04:45:11

问题


I have read materials below:

https://www.wikiwand.com/en/One_Definition_Rule

http://en.cppreference.com/w/cpp/language/definition

What is the difference between a definition and a declaration?

But still, can't figure out why it is One Definition Rule rather than One Declaration Rule?

I maintain that declaration is a subset of definition, so One Definition Rule is enough.


回答1:


Definition is a subset of declaration, not the other way around. Every definition is a declaration, and there are declarations that are not definitions.

int i = 3;      // definition and declaration
extern int i;   // ok: (re)declaration
int i = 4;      // error: redefinition

extern int j;   // declaration
extern int j;   // ok: (re)declaration
int j = 5;      // ok: (re)declaration and definition
int j = 6;      // error: redefinition



回答2:


One declaration rule would be too strict, preventing programs that use the same header more than once from compiling. It would also make it impossible to define data structures with back references.

A simple way to see the first point (using headers) is to consider a program composed of two translation units, A.cpp and B.cpp, which both include <string> header.

Translation units A.cpp and B.cpp are translated independently. By including <string>, both translation units acquire a declaration of std::string.

As for the second point (data structures with back references) consider an example of defining a tree in which each node has a back reference to its parent tree:

// Does not compile
struct tree {
    struct node *root;
};
struct node {
    struct node *left;
    struct node *right;
    struct tree *owner;
};

This example would not compile, because node from struct node *tree is undeclared. Switching the order of struct node and struct tree declarations wouldn't help, because then tree from struct tree *owner would be undeclared. The only solution in C and C++ is to introduce a second declaration for either of the two structs.




回答3:


Because the same declaration, in a .h file, may be included in multiple compilation units, and because multiple definitions is definitely a programming error, whereas multiple declarations isn't.




回答4:


Because when you have declared a function in a header file

// header toto.h
int f(void);

and you want to define it in the compilation unit where it belongs, you'd do

#include "toto.h"

int f(void) {
   return 0;
}

The definition is also a declaration, so this compilation unit sees two declarations, one in the header and one in the .c or .cpp file.

In short, the multiple declaration rule allows to check for consistency between different source files.




回答5:


The reason is really that the C++ translation model can easily deal with conflicting multiple declarations; it just requires the compiler part of the toolset to detect errors like this in the source code:

int X();
void X(); // error

A compiler can easily do that.

And when there are no such errors in any translation units, then there's no problem; every X() call in every translation unit is identical; what remains to do is for the linker to link every call to the one correct destination. The declarations have done their job and no longer play a role.


Now with multiple definitions, it's not that easy. Definitions are something which concerns multiple translation units and which goes beyond the scope of the compilation phase.

We've already seen that in the example above. The X() calls are in place, but now we need the guarantee that they all end up at the same destination, the same definition of X().

That there can be only one such definition should be clear, but how to enforce it? Put in simple terms, when it's time to link the object code together, the source code has already been dealt with.

The answer is that C++ basically chooses to put the burden on the programmer. Forcing compiler/linker implementors to check all multiple definitions for equality and detect differences would be beyond the capabilities of C++ toolsets in most real-life situations or completely break the way those tools work, so the pragmatic solution is to just forbid it and/or force the programmer to make sure that they are all identical or else get undefined behaviour.



来源:https://stackoverflow.com/questions/46988095/why-one-definition-rule-not-one-declaration-rule

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!