Let I've two cpp files:

//--a.cpp--//
class A
{
public:
    void bar()
    {
        printf("class A");
    }
};
//--b.cpp--//
class A
{
public:
    void bar()
    {
        printf("class A");
    }
};

When I'm compling and linking this files together I have no errors. But if I'll write the following:

//--a.cpp--//
int a;
//--b.cpp--//
int a;

After compiling and linking this sources I've an error as the redefiniton of a. But in the case of classes I've redefinition to, but there is no error is raised. I'm confused.

有帮助吗?

解决方案

Classes are types. For the most part, they are compile-time artifacts; global variables, on the other hand, are runtime artifacts.

In your first example, each translation unit has its own definition of class a. Since the translation units are separate from each other, and because they do not produce global runtime artifacts with identical names, this is OK. The standard requires that there be exactly one definition of a class per translation unit - see sections 3.2.1 and 3.2.4:

No translation unit shall contain more than one definition of any variable, function, class type, enumeration type, or template.

Exactly one definition of a class is required in a translation unit if the class is used in a way that requires the class type to be complete.

However, the standard permits multiple class definitions in separate translation units - see section 3.2.6:

There can be more than one definition of a class type, enumeration type, inline function with external linkage, class template, non-static function template, static data member of a class template, member function of a class template, or template specialization for which some template parameters are not specified in a program provided that each definition appears in a different translation unit, and provided the definitions satisfy the following requirements. [...]

What follows is a long list of requirements, which boils down to that the two class definitions need to be the same; otherwise, the program is considered ill-formed.

In your second example you are defining a global runtime artifact (variable int a) in two translation units. When the linker tries to produce the final output (an executable or a library) it finds both of these, and issues a redefinition error. Note that the rule 3.2.6 above does not include variables with external linkage.

If you declare your variables static, your program will compile, because static variables are local to a translation unit in which they are defined.

Although both programs would compile, the reasons why they compile are different: in case of multiple class definitions the compiler assumes that the two classes are the same; in the second case, the compiler considers the two variables independent of each other.

其他提示

There are actually two different flavors of the One Definition Rule.

One flavor, which applies to global and namespace variables, static class members, and functions without the inline keyword, says that there can only be one definition in the entire program. These are the things that typically go in *.cpp files.

The other flavor, which applies to type definitions, functions ever declared with the inline keyword, and anything with a template parameter, says that the definition can appear once per translation unit but must be defined with the same source and have the same meaning in each. It's legal to copy-paste into two *.cpp files as you did, but typically you would put these things in a header file and #include that header from all the *.cpp files that need them.

Classes can't be used (except in very limited ways) unless the definition is available within the translation unit that uses it. This means that you need multiple definitions in order to use it in multiple units, and so the language allows that - as long as all the definitions are identical. The same rules apply to various other entities (such as templates and inline functions) for which a definition is needed at the point of use.

Usually, you would share the definition by putting it in a header, and including that wherever it's needed.

Variables can be used with only a declaration, not the definition, so there's no need to allow multiple definitions. In your case, you could fix the error by making one of them a pure declaration:

extern int a;

so that there is only one definition. Again, it's common for such declarations to go in headers, to make sure they're the same in every file that uses them.

For the full, gory details of the One Definition Rule, see C++11 3.2, [basic.def.odr].

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top