Why does the C ++ compiler not support template header files and code separation compilation?

Source: Internet
Author: User

First, as mentioned in the C ++ standard, a compilation unit [Translation Unit] refers to A. cpp file and all. H files it includesCodeWill be extended to include it. in the CPP file, and then the compiler compiles. CPP file is. OBJ file, which has the PE [portable executable, that is, Windows Executable File] file format, and contains binary code, but it may not be executed, because it is not guaranteed that there must be a main function. Hosts file.

For example:

// --------------- Test. h -------------------//

Void F (); // declare a function f

// --------------- Test. cpp --------------//

# Include "test. h"

Void F ()

{

... // Do something

} // The F function declared in test. H is implemented here.

// --------------- Main. cpp --------------//

# Include "test. h"

Int main ()

{

F (); // call F, F has an external connection type

}

In this example, test. CPP and Main. CPP is compiled into different ones. OBJ file [name it test. OBJ and Main. OBJ], in Main. in CPP, F function is called. However, when the compiler compiles main. only main. test. the declaration of void F (); in the H file. Therefore, the compiler regards F as an external connection type, that is, its function implementation code is in another. in the OBJ file, this example is test. OBJ, that is, Main. OBJ does not actually have a line of binary code about the f function, and the Code actually exists in test. test. OBJ. Calling F in Main. OBJ generates only one line of Call Command, as shown in the following figure:

The name in call f [C ++ is of course mangling [Processed]

During compilation, this call command is obviously incorrect, because main. OBJ does not have a line of F implementation code. What should we do? This is the task of the connector. The connector is responsible for other tasks. in OBJ [this example is test. OBJ] Find the implementation Code of F and replace the call address of the call f command with the actual entry point address of the f function. Note that, on the connector, The .obj.pdf in the project is connected to a. EXE file, and the most critical task is to find an External Connection Symbol in another. OBJ address, and then replace the original "false" address.

This process is more in-depth:

The call f command line is actually not like this. It is actually called stub, that is, a JMP 0x23423 [this address may be arbitrary, however, the key is that there is a line of command on the address to perform the real call f action. That is to say, all calls to F in this. OBJ file are directed to the same address by JMP, and the latter only truly calls "F. The advantage of this is that when the connector modifies the address, you only need to modify the call XXX address of the latter. However, in this example, the connector is located in test.obj. because the format of .objyu .exe is the same, there is a symbol import table and symbol export table in this file. [Import
In table and export table], all symbols are associated with their addresses. In this way, the connector only needs to be in the test. in the OBJ symbol export table, find the address of the symbol F [of course C ++ has done mangling for F]. Then, after some offset processing, [because two. OBJ file merge, of course, the address will be offset, this connector is clear] write into main. the one that the symbol F occupies in the OBJ import table.

This is the general process. The key is:

When compiling main. CPP, the compiler does not know the implementation of F. All calls to it only give an indication that the connector should look for the implementation body of F for it. That is to say, Main. OBJ does not have any line of binary code about F.

When compiling test. CPP, the compiler finds the implementation of F. As a result, the implementation of F [binary code] appears in test. obj.

During connection, the connector finds the address of the implementation code [binary] of F in test. OBJ [export table by symbol]. Then, change the pending call XXX address in Main. OBJ to the actual address of F.

As for the template, you know that the code of the template function cannot be directly compiled into binary code, and there must be a "current" process.For example:

// ---------- Main. cpp ------//

Template <class T>

Void F (t)

{}

Int main ()

{

... // Do something

F (10); // call F <int> the compiler decides here to give F a cash body of F <int>

... // Do other thing

}

That is to say, if you have not called F in the main. cpp file, F will not be available, so there will be no line of binary code about F in Main. OBJ !! If you call:

F (10); // F <int> can be activated

F (10.0); // F <double> can be activated

In this way, F <int> and F <double> are included in Main. obj. And so on.

However, the compiler is required to understand the template definition, right?

See the following example: [separating the template from its implementation]

// ------------- Test. h ----------------//

Template <class T>

Class

{

Public:

Void F (); // here is just a declaration

};

// --------------- Test. cpp -------------//

# Include "test. h"

Template <class T>

Void a <t>: F () // template implementation, but note:

{

... // Do something

}

// --------------- Main. cpp ---------------//

# Include "test. h"

Int main ()

{

A <int>;

A. F (); // The Compiler does not know the definition of a <int>: F, because it is not in test. h.

// So the compiler had to hope for the connector, hoping it could be found in other. OBJ

// A <int>: The implementation body of F. In this example, It is test. obj. However, the latter actually has a <int >:: F

// Binary code? No !!! The C ++ standard clearly indicates that when a template is not used

// Shouldn't it be discovered, and a <int>: F is used in test. cpp? No !! Therefore

// In the test. OBJ file compiled by test. CPP, the binary code of A: F does not exist either.

// The connector is dumpfounded, so a connection error is returned.

// However, if you write a function in test. cpp and call a <int>: F, the compiler

// Come out, because at this point [test. cpp], the compiler knows the template definition, so it can

// If it is ready for use, the "A <int>: F" symbol is available in the test. OBJ export table.

// Address, so the connector can complete the task.

}

In a separate compilation environment, the compiler compiles a file. the CPP file does not know another one. the existence of the CPP file does not look for [it is expected to be a connector when there is a pending symbol]. This mode runs well without a template, but it is dumpfounded when it comes to a template, because the template is only available when necessary. Therefore, when the compiler only sees the template declaration, it cannot present the template. It can only create a symbol with an external connection and expects the connector to determine the address of the symbol. However, when this template is implemented. when the template is not used in the CPP file, the compiler is too lazy to use the template. Therefore, the entire project. OBJ cannot find a line of binary code with the template as the entity, so the connector is also silly!

Post: http://blog.csdn.net/thinkscape/article/details/3567420

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.