C ++ File include rule constant definition

Source: Internet
Author: User
Tags constant definition

C ++ File include rule constant definition

To sum up, C ++'s function declaration, variable declaration, and class definition are written in the header file, while function implementation, variable definition, and class method implementation are written in. cpp file; but for inline functions and template classes, the function implementation should also be written in the header file !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!


1. write the definition of the member variables and class methods of the class in. h, write the implementation of class methods in. in cpp, do not include. cpp file, not in. only write class MyClass in the H file; Be sure to writeAll class member variables and methods are defined !!! The implementation of class methods is written in the. cpp file.

2. Class templates or template DefinitionsBe sure to write it in the same. h. Do not write it in. cpp. Do not write it separately !!!See the explanation in the http://blog.csdn.net/ixsea/article/details/6695496: For template functions,Only the called template function is instantiated.In this example, it is not required to be called by the main function. If a common function calls a template function, the template function generates an instance. The common function called by the template function may not be called by main or executed. The reason that common functions. h and. cpp can be separated is that they have been instantiated, so you can find the function implementation location according to the definition in. h !!!Full text:

Certificate ----------------------------------------------------------------------------------------------------------------------------------------

Opinion

The inclusion model is an organization of the C ++ template source code. It encourages you to put all the template code in A. h header file to avoid inexplicable Link errors.

Inexplicable Link error

In general, programmers are used to placing function and class declarations in. H files and their implementations in. cpp files. This multi-file organization method has been advocated. On the one hand, this separation makes the code logic clear. To understand which global functions and classes the program uses, you only need to view the. h file. If we put together the declaration and implementation, the troubles can be imagined. It is a torment to find function names, class names, and member names in a pile of messy code. On the other hand, this organization mode is required when building a dynamic link library. Because the dynamic link library is code reuse at the binary level, its major advantage is that the specific implementation process is hidden, and it is obviously not in line with the requirements in a. h file.

However, unfortunately, when programmers still write template code according to this good habit, there is a problem. For example, the following simple example:

  1. // Bigger. h
  2. Template
  3. T Bigger (T, T );
  4. // Bigger. cpp
  5. # Include "Bigger. h"
  6. Template
  7. T Bigger (T a, T B)
  8. {
  9. Return a> B? A: B;
  10. }
  11. // Main. cpp
  12. # Include "Bigger. h"
  13. # Include
  14. Using namespace std;
  15. Int main ()
  16. {
  17. Cout < System ("pause ");
  18. Return 0;
  19. }

    These lines of code are very simple. They are divided into three files: Bigger. h, Bigger. cpp, and main. cpp, which correspond to the declaration, definition, and use of the template function Bigger respectively. It seems that the structure is clear and complies with good coding habits, but the compilation link gets the following error message:

    Error 1 error LNK2019: unresolved external symbol "int _ cdecl Bigger (Int, int )"(?? $ Bigger @ H @ YAHHH @ Z) referenced in function _ main E: \ Codes \ Chapter3Lab \ includeModel \ main. obj
    The linker cannot find Bigge in main. obj. Function implementation. This seemingly unreasonable Link error also reflects the template instantiation rules.

    Template instantiation rules

    For a template function, only the called template function is instantiated. The called function does not require it to be called by the main function. If a common function calls a template function, the template function generates an instance. The common function called by the template function may not be called by main or executed.
    Template classes also have type instantiation rules. In particular, even if a class template is explicitly instantiated, the member functions of the class template may not be instantiated. This is an "incomplete" instantiation rule of the template class, you can click here to learn more.

    Link error explanation

    After learning about the template instantiation rules, you can explain the above Link errors. Main. in cpp, Bigger () is called. This will cause the template function Bigger (T, T) to be instantiated as a common function. However, in main. the translation unit to which cpp belongs is not implemented by Bigger (T, T. for the Translation Unit of cpp, the implementation of Bigger (T, T) is invisible. Therefore, when the main. cpp translation unit is compiled to obtain main. obj, the compiler assumes that Bigger (Int, int) in other translation units.

    Bigger. although cpp has the implementation of Bigger (T, T. bigger is not called in the Translation Unit of cpp, so Bigger. cpp has no obligation to instantiate the template function Bigger (T, T. bigger that cannot be found in obj (Int, int ).

    The Link error message in the above example is exactly what it means.

    Further exploration of Link errors

    Since Bigger. cpp is not obligated to instantiate Bigger (T, T), add a call to Bigger. cpp (Int, int) can a common function be used? Add several lines of code to the Bigger. cpp file, as shown below:

    1. // Bigger. cpp
    2. # Include "Bigger. h"
    3. Template
    4. T Bigger (T a, T B)
    5. {
    6. Return a> B? A: B;
    7. }
    8. Void g () // Add a call to Bigger (Int, int) Ordinary Function g ()
    9. {
    10. Bigger (1, 2 );
    11. }

      The above points are further verified when the compilation and link are successful and the results are correct.

      Solution-include model

      The examples listed in this article are very simple and small in size. Therefore, according to the template instantiation rules, "manually" is involved in the template function instantiation process and the program runs successfully. However, in a large program, it is almost impossible to control human intervention. The inclusion model recommended by C ++ should be used.

      The specific method is not complex: place the template declaration and definition in A. H file. All the. cpp files that use the template include the. h file. In the above example, the code is rewritten using the include model:

      1. // Bigger. h
      2. Template
      3. T Bigger (T a, T B)
      4. {
      5. Return a> B? A: B;
      6. }
      7. // Main. cpp
      8. # Include "Bigger. h"
      9. # Include
      10. Using namespace std;
      11. Int main ()
      12. {
      13. Cout < System ("pause ");
      14. Return 0;
      15. }

        But there is still a question worth thinking about: what is the size of the inventory file? This problem exists theoretically, but most compilers have optimized it. When the same type of a template has multiple instantiated bodies, the compiler will eventually retain only one, this avoids code expansion.


        The following is an example:

        // Main. cpp

        #include "person.h"#include "SmartPointer.h"using namespace std;int test() {  //auto_ptr
               
                 p(new person("Cici"));  //SmartPointer
                
                  p(new person("Cici"));  //p -> tell();  SmartPointer
                 
                   r(new person("taoqi"));  SmartPointer
                  
                    p(new person("Cici"));    p -> tell();    {  SmartPointer
                   
                     q = p;      q -> tell();      r = q;  SmartPointer
                    
                      s(r); s -> tell(); } r -> tell(); return 0;}int main(){ test(); return 0;}
                    
                   
                  
                 
                
               

        // SmartPointer. h
        #ifndef SMARTPOINTER_H#define SMARTPOINTER_Htemplate
               
                class SmartPointer{public:  SmartPointer(T* ptr);  ~SmartPointer();  SmartPointer(SmartPointer
                
                 & sptr);  T* operator->();  T& operator*();  SmartPointer
                 
                  & operator=(SmartPointer
                  
                   & sptr);  T getValue();protected:  T* ref;  unsigned* ref_count;};template
                   
                    SmartPointer
                    
                     ::SmartPointer(T* ptr){ ref = ptr; ref_count = (unsigned*)malloc(sizeof(unsigned)); *ref_count = 1;}template
                     
                      SmartPointer
                      
                       ::~SmartPointer(){ --*ref_count; if (*ref_count == 0) { delete ref; free(ref_count); ref = NULL; ref_count = NULL; }}template
                       
                        SmartPointer
                        
                         ::SmartPointer(SmartPointer
                         
                          & sptr) { ref = sptr.ref; ref_count = sptr.ref_count; ++(*ref_count);}template
                          
                           T* SmartPointer
                           
                            ::operator->() { return ref;}template
                            
                             T& SmartPointer
                             
                              ::operator*() { return *ref;}template
                              
                               SmartPointer
                               
                                & SmartPointer
                                
                                 ::operator=(SmartPointer
                                 
                                  & sptr){ if (this != &sptr) { ref = sptr.ref; ref_count = sptr.ref_count; ++(*ref_count); } return *this;}template
                                  
                                   T getValue() { return *ref;}#endif
                                  
                                 
                                
                               
                              
                             
                            
                           
                          
                         
                        
                       
                      
                     
                    
                   
                  
                 
                
               
        // Person. h

        #ifndef PERSON_H#define PERSON_H#include 
               
                #include 
                
                 using namespace std;class person{public:  person(string name);  ~person(void);  void tell();private:  string name;};#endif
                
               

        // Person. cpp

        #include "person.h"person::person(string name):name(name){}void person::tell(){  cout << "Hi! I am " << name << endl;}person::~person(){  cout << "Bye!" << endl;}

        Another article about internal links and external connections:

        Http://www.cnblogs.com/magicsoar/p/3840682.html


        Internal link and external link

        So what are internal and external links?

        We know that the declarations and definitions in C ++ can be separated.

        For example, in vs, we can place a function Declaration definition in B. cpp. In a. cpp, we only need to declare this function to use it in a. cpp.

        A. cpp

        void show();int main(){    show();return 0;}

        B. cpp

        #include 
               
                void show(){    std::cout << "Hello" << std::endl;}
               

        Through previous understanding, we know that each compilation unit is independent of each other and does not know the existence of each other.

        So how does a. cpp know the definition of the show function?

        In fact, when compiling a compilation unit (. cpp) to generate the corresponding obj file

        The compiler will analyze this compilation unit (. cpp)

        Record the variable definitions of the functions that can be provided to other compilation units (. cpp.

        And record the missing functions and variable definitions.

        Therefore, we can assume that a. obj and B. obj record the following information:

        Then you will know. obj requires the show function definition, while B. obj exactly provides the definition of the show function. Through the link, we can see the running of the show function in the final executable file.

        What are the relationships between these external links and internal links?

        The compilation units (. cpp) can be compiled to other units (. cpp) display, provide its definition, and let other compilation units (. cpp). variables are external links, such as global variables.

        The compilation units (. cpp) cannot be displayed to other compilation units (. cpp) and provide the defined functions. The variables are internal links, such as static functions and inline functions.

        Let's take a look at the compilation unit. The internal link and external link are more formal definitions.

        Compilation unit: When a c or cpp file is being compiled, the Preprocessor first recursively contains the header file to form a single source file containing all necessary information. This source file is a compilation unit.

        Internal Connection: If a name pair is used to compile the unit (. cpp) is local. When linking, other compilation units cannot be linked to it and will not be linked to other compilation units (. the same name in cpp.

        External Connection: If a name is not local to the compilation unit (. cpp), other compilation units can access it during the link, that is, it can interact with other compilation units.

        Certificate ----------------------------------------------------------------------------------------------------------------------------------------

        3. Use the following two methods to prevent repeated include:

        # Ifndef PERSON_H
        # Define PERSON_H
        # Endif

        Or

        # Pragma once


        4. Write the available constants, File Scope constants, and global constants in the definition class:

        A. class member variables cannot be initialized when the member variables are defined (unless it is const static). Therefore, the member variable initialization list is the only opportunity for the const variable initialization at this time... Write

        Class MyClass {

        Private:

        Const int a1 = 3;

        Const char * s1 = "abc ";

        }

        It's a big mistake and special mistake !!!! At the same time, note that the initialization can only be performed in the initialization list of the constructor.

        B. when defining a global variable, extern int a; is declared and not defined, but extern int a = 3 is defined; of course, it can be defined in. in cpp, extern int a = 3; in B. extern int a; in cpp. However, a more standard approach is to throw extern int a to B. cpp header file B. in h, in B. in cpp, only int a = 3 is defined. When other files are used, only # include "B. h.

        C. static const int a = 3; to be written in. cpp, because it is only used in this file. The. h file is for others to include:

        Therefore, the correct code is:

        // Main. cpp

        //main.cpp  #include"MyClass.h"  #include
               
                  using namespace std;  int main()  {    MyClass myClass(30,"abc");      cout << "a2 = " << a2 << endl;  cout << "s2 = " << s2 << endl;  return 0;  }  
               

        // MyClass. cpp

        //MyClass.cpp#include "MyClass.h"  #include 
               
                using namespace std;const int a2 = 2;const char* const s2 = "s2";static const int a3 = 3;static const char* const s3 = "s3";MyClass::MyClass(const int a = 30, const char* const s = "abc"):a1(a),s1(s){  cout << "a3 = " << a3 << endl;  cout << "s3 = " << s3 << endl;}
               

        // MyClass. h

        //MyClass.h#ifndef MYCLASS_H#define MYCLASS_Hextern const int a2;extern const char* const s2; class MyClass {private:  const int a1;  const char* const s1;public:  MyClass(const int a, const char* const s);};#endif

        5. inline functions must be written in the header file:

        The inline function is characterized by inserting the code of the corresponding function at the place where it is called, so there is no inline function body in the target file after compilation, because it has been replaced by the corresponding statement in the place where it is to be called (of course, this is only limited to the case where inline is successful ).
        If we write the inline function in the cpp file, but in most cases, when we use a third-party class library, we only have the header file and the target file (No cpp file ), when you call that inline function, the compiler cannot find it. Therefore, writing inline functions in the cpp file is useless.

        6. the last record is the log of initialization of different variables such as const and static:

        Http://blog.csdn.net/gljseu/article/details/9750877


        1. Common variables: assign values in constructors without considering the efficiency. For efficiency, you can perform this operation in the initialization list of the constructor.

        Class CA

        {

        Public:

        Int data;

        ......

        Public:

        CA ();

        ......

        };

        CA: CA (): data (0 )//...... #1 ...... Initialize the list

        {

        // Data = 0 ;//...... #1 ...... Assignment Method

        };

        2. static variables:

        Static variables belong to all classes but not class objects. Therefore, no matter how many objects the class is instantiated, this variable has only one. In terms of this nature, it is somewhat similar to the uniqueness of global variables.

        Class CA

        {

        Public:

        Static int sum;

        ......

        Public:

        CA ();

        ......

        };

        Int CA: sum = 0 ;//...... #2 ...... Class initialization

        3. const constant variable:

        The const constant must be initialized upon declaration. Therefore, Initialization is required when a variable is created. It is generally carried out in the initialization list of the constructor.

        Class CA

        {

        Public:

        Const int max;

        ......

        Public:

        CA ();

        ......

        };

        CA: CA (): max (100)

        {

        ......

        }

        4. Reference variables:

        The referenced variable is similar to the const variable. It must be initialized at the time of creation. Also in the initialization list. Note that the Reference type is used.

        Class CA

        {

        Public:

        Int init;

        Int & counter;

        ......

        Public:

        CA ();

        ......

        };

        CA: CA (): counter (& init)

        {

        ......

        }

        5. const static integral variable:

        C ++ is privileged for both const and static and integer variables (but different compilers may have different support, which does not seem to be supported by VC 6 ). It can be initialized directly in the class definition. Short works, but float does not.

        // For example, the float type can only be initialized outside the class.

        // Const float CA: fmin= 3.14;

        Class CA

        {

        Public:

        // Static const float fmin = 0.0; // only static const integral data members can be initialized within a class

        Const static int nmin = 0;

        ......

        Public:

        ......

        };

        To sum up, there are four possible initialization conditions:

        1. In the class definition, only the const and static and integral variables are involved.

        2. In the class constructor initialization list, including the const object and Reference object.

        3. initialized outside the class definition, including static variables. Because it is a unique variable of the class.

        4. Common variables can be assigned within the constructor. Of course, this is inefficient.

        Class Definition body can only initialize the const integral data type. Put the static type in the. cpp file! Of course, it cannot be placed in member functions. (Static data members can be used for non-static member functions! Static member functions can only call static data members .), Because the static volume is a class, not an object. In this case, every object is used to operate all objects (classes). It is not a mess, so this behavior cannot be allowed.
        However, the static value can be assigned to the class constructor. Of course, it cannot be placed in the initialization member list. However, copy construction cannot be used when assigning values in the constructor.Error:
        Term does not evaluate to a function taking 1 arguments
        The declaration and definition of the static function in the class are as follows:
        The declaration of a static function can be declared like a common member function, but a static keyword is added before it.
        For example:
        Private:
        Static int GetXYZ ();
        In definition, static keywords cannot be added like static variables. If it is written as follows:
        Static int A: GetXYZ ()
        {
        ............
        }
        The following message is displayed:
        'Static 'shoshould not be used on member functions defined at file scope
        Therefore, it should be written as follows:
        Int A: GetXYZ ()
        {// The property of a static function. use other methods to identify it. For example, write this is a static function.
        ............
        }
        As for the use of static functions, you can insert them in the code segment you have written as follows:
        ..................
        A: GetXYZ (); // it can be seen that it is A class, not an object
        ..................
        Of course, for the public Type static volume (for example, CString S_str), you can use the following method:
        A: S_str = "Hello! ";
        CString str = A: S_str;

        C ++ member variable initialization problem category: c/c Summary

        C ++ provides the class member initialization list for the class.

        The construction order of class objects is as follows:

        1. allocate memory. when calling the constructor, the data members are initialized implicitly/displayed.

        2. After Entering the constructor, execute general calculations in the constructor.

        1. Any member variables in the class cannot be initialized during definition.

        2. Generally, data members can be initialized in the constructor.

        3. the const data member must be initialized in the const initialization list.

        4. static should be initialized outside the class definition.

        5. array members cannot be initialized in the initialization list.

        6. You cannot specify an Explicit initialization for the array.

        These six items indicate a problem: the constant array cannot be defined in C ++! Because of the conflict between 3 and 5. Can't this happen? No way, I had to turn to static data members.

        At this point, my problem is solved. But I also want to take the opportunity to review C ++ class initialization:

        1. Initialization list: CSomeClass (): x (0), y (1 ){}

        2. Out-of-class initialization: int CSomeClass: myVar = 3;

        3. the const constant definition must be initialized, and the initialization list should be used in the C ++ class;

        4. The C ++ class cannot define a constant array.






Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.