Incomplete type and Foreward declaration

Source: Internet
Author: User

Sometimes we encounter some compiler errors related to incomplete types during programming. At this time, we often simply change it to the corresponding complete type definition, and we don't have time to think about why the error is reported, there are no other better solutions; there are also many people who will include all the header files that can be included in November 21, regardless of whether they are compiled. In many cases, a custom type does not need to contain its header file. Therefore, I wrote an article today to summarize these issues.

Incomplete Type
Incomplete types, including incompletely-defined object type and void ). We all know that the null type is mainly used in function return values and null pointers. The former is the focus of today's research. It is a fuzzy type that is unknown to all sizes, layout, and alignment requirements.

The following lists some common incomplete types:

// Main. cpp
 
// Variable definition. The compilation fails because the array size is unknown.
Char a [];
// Variable definition, because type A is undefined and cannot be compiled
A B;
// Variable definition. Although the size is determined, type A is undefined and cannot be compiled.
A c [10];
 
Int main ()
{}
These global objects only provide incomplete types when being defined, and their size and other information compilers cannot be informed, so they cannot be compiled. What is the use of incomplete types? The following is a small example.

// A. cpp
Char a [10] = "123456789 ";
 
// Main. cpp
# Include <iostream>
Using namespace std;
 
// Variable declaration, which is an incomplete type
Extern char a [];
 
Int main (){
 
// After compilation is successful, 1 to 9 are printed.
For (int I = 0; a [I]! = '\ 0'; ++ I)
Cout <a [I] <endl;
 
// The following compilation fails.
// Cout <sizeof (a) <endl;
}
Here, we found that incomplete types can be used in declarations rather than definitions. Because the Declaration does not need to know the object size, memory layout, and other information. In addition, we also found that although the declared object of the incomplete type has no problem, the subsequent operations determine whether the object can be compiled. Print the element section of the array, because the element type (char) is known and does not need to know its size (because we determine whether it ends Based on the ending NUL character ), so there is no problem with compilation. However, if you need to print the array size, the compilation will fail, because a is still incomplete.

The above example only describes the use of incomplete types and is not very practical. Because other arrays (such as integer arrays) do not end with special characters (such as NUL. If we don't even know the size of the array, what does it mean to operate on it? Therefore, in actual projects, it is more common to declare using the complete type, such:

Extern char a [10];
Forward Declaration

The real application appears in the forward Declaration of the class.

// A. h
Class
{...}
 
// B. h
// Forward Declaration
Class;
 
Class B
{
Private:
// The following A types are incomplete
A * m_a;
Int calculate (const A & a1, const A & a2 );
}
I wonder if you have found that B .h does not include the header file of Class A, but it can be compiled. Why? Because it is not required, only the pointer and reference pointing to A are used in the header file. The C ++ standard does not require the complete information of Class A to define these two variables. When will it be necessary? When A member function or object of A is called by pointer or reference.

// B. cpp
// Haha, now I have A complete definition of A. You can call its members through "-> ", ".", ":".
# Include "A. h"
# Include "B. h"
 
Int B: calculate (const A & a1, const A & a2)
{
Return (a1.GetValue () * a2.GetValue ());
}
Here we will talk about the complete information of the class through "->", "." or ":" to call any member of the class, or B to inherit from. Some colleagues may wonder: why is it so difficult to include A's header file directly? Well, if you are interested, you can read this article and leave a suspense here.
In addition to this application, there is another purpose: to solve the circular dependency between classes.

// A. h
Class Fred
{
Public:
Barney * foo (); // Error: Unknown symbol 'barnin'
};
 
Class Barney
{
Public:
Fred * bar ();
};
Here, no matter which class is put before, compilation errors will occur. The solution is to add a forward statement at the beginning.
Class Barney;
 
Class Fred
{...};
 
Class Barney
{...};
In the C ++ FAQ, I explained it again. If you are interested, you can check it out.

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.