Code redefinition

introduction

    Redefinition, in a nutshell is the same variable defined twice or more times. As shown in the following code, as defined in test.h in a class, but I have cited test.h file in add.h and main.cpp, this time in the process of compilation will produce an error.

Test code

/*****test.h*****/
class Test{
public:
    int i;
};
/*****add.h*****/
#include "test.h"

int Add1(int a,int b);
/*****add.cpp*****/
#include <iostream>
#include "add.h"

int Add1(int a, int b)
{
  Test test_add;
  std::cout<<"This Add1 function"<<std::endl;
  return a+b;
}
/*****main.cpp*****/
#include <iostream>

#include "add.h"
#include "test.h"

int main()
{
  Test test_main;
  std::cout<<"Run main"<<std::endl;
  std::cout<<"1+1="<<Add1(1,1)<<std::endl;
  return 0;
}

How to avoid

1. Use #ifndef

    #Ifndef during use macro commands may be employed to avoid this problem, use is as follows:

#ifndef MY_TEST_TEST_H
#define MY_TEST_TEST_H
class Test{
public:
    int i;
};
#endif //MY_TEST_TEST_H

    ifndef this conditional compilation is to prevent the same cpp file contains more than in the same .h your main document (such as a main.cpp file contains test.h, add.h but also contains test.h, then when when .cpp quote Add function will #include <test.h> (because of the above conditions have compiled without error), because the compiler at compile time is compiled as a unit in accordance with cpp files, each cpp file compiled .o file, and then link them together .o files, and finally form an executable file with runtime link you included with a .h file in two cpp files. this is the fundamental and conditional compilation does not matter. you defined in the Test class .h file so it means you two cpp file, each cpp file has such a global variable definition:. class Test; when each cpp file compiled separately of course, no problem, but when they link up when problems arise: two cpp files have variable Test class, so of course, is to repeat the definition ah problem is linked in time
    although the use of conditional compilation can solve this problem, but with text Parts can lead to increased macro obviously be repeated, this time will cause problems conditional compilation failure. And every time the compiler need to open the header file in order to determine whether there are duplicate definitions, so when compiling large projects, # ifndef will compile time so that a relatively long, thus beginning to support some compilers #pragma once manner.

2. Use #pragma once

    May be employed during use #pragma once macros to avoid this problem, use is as follows:

#pragma once
class Test{
public:
    int i;
};

    You can not make #pragma once statement on a piece of code in the header file, but only for the file. The benefit is that you do not have to worry about the macro name conflict, of course, conflict-induced strange macro name does not appear. Compilation speed large-scale projects and thus improve a little. When cross-platform, some platforms do not support this use, now, I have not encountered.

3. Using an anonymous namespace (expand)

    Use as follows:

namespace {
  class Test{
  public:
    int i;
  };
}

    The compiler will generate a unique name for this namespace inside, but also generates a using directive for the anonymous namespace. So in effect the above code is equivalent to:

     namespace __UNIQUE_NAME_ {
         class Test{
         public:
             int i;
         };
     }
     using namespace __UNIQUE_NAME_;

    Why use an anonymous space redefinition of variables can also be prevented, because the anonymous space has internal link attribute, which is declared as link attributes and static global name is the same, that the scope is limited to the name of the current file, you can not to be linked by using extern declared in another file. If you do not promote the use of the name has to declare a global static internal link attribute, the anonymous namespace can be used as a way to achieve the same effect better.

Three kinds of link attributes (expand)

Link attributes (linkage) divided into three types - external (external), internal (internal), no (none).

External attributes : External link attribute means, an identifier can be used not only in the current source file, the file can also be used in other programs.
Internal attributes : use modified static identifier has internal linkage property, valid only in the source file. const modified internal links is also the default attribute, when there is extern const, extern const attribute pressure over the property, the property became external links.
None Attributes : local variables.

Reflection

    Why write this article. This is because there has been redefined variables in practice, the use of const char * str = "test" in test.h in; I was using the #pragma once in the header file, but no effect, I used anonymous space before we can solve the problem. Why is this?
    Header files are generally stored declare variables, defined variables should not be stored. And I was stored is the definition of variables, and multiple file references, resulting in an error, a problem when still wondering, plus the #pragma once, there will be such a problem, it does not make sense! ! ! If you are reading this article, you will ask const said above is modified internal link attribute, I use const char why would an error?
    const variables are modified internal link attribute, then no doubt. Wrong reasons is because I use a const char
, const modified at this time is char, rather than a pointer variable str, str so here is global. If const pointer variable is modified the p-(char const str), this time outside str link is not visible, so the problem I encountered can also speak const char into a char * const or const std :: string (this time using std :: string a bit overkill)

Reference links

Anonymous space: https://www.cnblogs.com/youxin/p/4308364.html
Link Properties: https://blog.csdn.net/u011285208/article/details/94738969
const Internal link properties: HTTPS: // the WWW .cnblogs.com / sheshiji / p / 3427896.html

Guess you like

Origin www.cnblogs.com/SmallBlackEgg/p/12522173.html