Current location - Education and Training Encyclopedia - Graduation thesis - Ask for a paper about C++
Ask for a paper about C++
Regarding the unreasonable design of C++ constructor in C++, constructor is a special function called when building an object, and its purpose is to initialize the object and make it in a reasonable state before use. However, the design of the constructor is not perfect and even has some unreasonable characteristics. For example, qualify the condition that the constructor name is the same as the class name. These characteristics are worthy of attention when constructing C++ compiler. In addition, these features should be avoided when modifying the C++ standard or formulating other object-oriented design languages in the future. This paper also puts forward some solutions.

In C++, any class has one (at least one) constructor, even if no constructor is declared. These constructors are called when an object is declared or dynamically generated. Constructors do a lot of invisible work, even if there is no code in the constructor, including memory allocation of objects and initialization of members by assignment. The name of the constructor must be the same as the name of the class, but many different overloaded versions can be provided, and the versions of the constructor are distinguished by the parameter types. Constructors can be explicitly called by user code or implicitly inserted by the compiler when the code does not exist. Of course, it is recommended to call explicitly through code, because the effect of implicit call may not be what we expected, especially when dealing with dynamic memory allocation. The code calls a unique constructor through parameters. Although the statement can be returned in the function body, the constructor does not return a value. Each constructor can instantiate an object in different ways, because each class has a constructor, at least the default constructor, so each object uses the constructor accordingly before using it. Because the constructor is a function, its visibility is nothing more than public, private and protected. Usually, constructors are declared public. If the constructor is declared as private or protected, the instantiation of the object will be restricted. This is effective in preventing classes from being instantiated by other classes. There can be any C++ statement in the constructor, such as the print statement, which can be added to the constructor to indicate the location of the call.

There are many types of constructors in the constructor type C++. The most commonly used default constructors and copy constructors also have some less commonly used constructors. There are four different constructors.

1, default constructor

The default constructor is a function with no parameters. In addition, the default constructor can also be declared as the default value of the parameters in the parameter list. The default constructor is used to initialize the object to the default state. If there is no constructor explicitly defined in the class, the compiler will automatically create one implicitly, which is similar to an empty constructor. He doesn't do anything, he just makes examples of objects. In many cases, the default constructor will be called automatically, such as declaring an object, which will lead to the call of the default constructor.

2. Copy the constructor

Copy constructor, usually called x (x&; ), a special constructor, is called by the compiler to initialize some components and other objects based on the same class. Its only parameter (a reference to an object) is immutable (because it is of const type). This function is usually used to pass and return values of user-defined types during function calls. The copy constructor calls the copy constructor and member function of the base class. If possible, it will be called in a constant way, and in addition, it can be called in an unconventional way.

In C++, there are three situations where you need to copy an object. Therefore, the copy constructor will be called.

1) An object is passed into the function body by value.

2) Return an object from a function by value passing.

3) One object needs to be initialized by another object.

The above situation requires copying the call of the constructor. If the copy constructor is not used in the first two cases, it will cause the pointer to point to the deleted memory space. For the third case, the different meanings of initialization and assignment are the reasons for the constructor call. In fact, the copy constructor is implemented by a general constructor and an assignment operation. There are many references describing the similarities and differences between copy constructors and assignment operators.

The copy constructor cannot change the object it refers to for the following reasons: When an object passes a function by passing a value, the copy constructor is automatically called to generate the object in the function. If an object is passed into its own copy constructor, its copy constructor will be called to copy the object, so that the copy can be passed into its own copy constructor, which will lead to an infinite loop.

In addition to being implicitly called when the object is passed into the function, the copy constructor is also called when the object is returned by the function. In other words, all you get from the function is a copy of the object. But again, the copy constructor is called correctly, so don't worry.

If you don't explicitly declare a copy constructor in the class, then the compiler will privately make a function for you to copy bitwise between objects. This implicit copy constructor simply associates all class members. Many authors will refer to this default copy constructor. Note that the difference between an implicit copy constructor and an explicitly declared copy constructor lies in the way members are related. An explicitly declared copy constructor is only associated with the default constructor that instantiates a class member, unless another constructor is called during class initialization or list construction.

Copying the constructor makes the program more efficient because it doesn't have to change the constructor's parameter list when constructing the object. Designing a copy constructor is a good style, even if the compilation system helps you apply for the default copy constructor in memory. In fact, the default copy constructor can handle many situations.

3. User-defined constructor

User-defined constructors allow objects to be initialized while being defined. This constructor can have any type of parameters. User-defined and other types of constructors are contained in the class mystring: ClassMyString.

{ ......

public:mystring(); //Default constructor

My String (My String & ampsrc)

//Copy the constructor

mystring(char * SCR);

//Forced constructor

mystring ( char scr[ ],size _ t len);

//User defined constructor};

4. Forced constructor

In C++, you can declare a constructor with only one type conversion parameter. Forces the constructor to specify a type conversion (implicit or explicit) from the parameter type. In other words, the compiler can call the constructor with an instance of any parameter. The purpose of this is to create a temporary instance to replace the instance of the parameter type. Note that the keyword explicit recently added to the standard C++ is used to prohibit implicit type conversion. However, not all compilers support this feature. The following is an example of a mandatory constructor:

Level a

{

Public:

A(int ){ }

};

void f(A) { }

void g()

{

a My _ Object = 17;

A a2 = A(57);

a3(64);

My _ Object = 67

f(77);

} like a my _ object =17; This declaration means calling the A(int) constructor to generate an object from an integer variable. Such a constructor is a mandatory constructor.

General features The following are some unreasonable designs of C++ constructors. Of course, there may be other unreasonable places. However, in most cases, we still have to deal with these features and explain them one by one. The 1. constructor can be inline, but don't do this.

Generally speaking, most member functions can become inline functions by adding the keyword "inline" in front of them, and constructors are no exception, but don't do this! The constructor defined as inline is as follows: class X.

{ ..........

public:x(int);

};

Inline x::x(int)

{...} In the above code, the function is inserted into the program code, not as a separate entity. This will improve the efficiency of a function with only one or two statements because there is no overhead of calling the function.

The danger of using inline constructors can be reflected in defining static inline constructors. In this case, the static constructor should be called only once. However, if the header file contains a static inline constructor and is contained by other units, the function will be copied many times. In this way, when the program starts, all copies of the function will be called instead of one copy that the program should call. The fundamental reason is that static functions are real objects disguised as functions.

One thing to remember is that inlining is a suggestion, not a compulsion, and the compiler generates inline code. This means that inlining is implementation-related, and different compilers may bring many differences. On the other hand, inline functions may include more than just code. Constructors are declared inline, and all constructors containing objects and base classes need to be called. These calls are implicit in the constructor. This may create a large inline function segment, so it is not recommended to use inline constructors. 2. The constructor has no return type.

It is an error to specify the return type for the constructor, because it will introduce the address of the constructor. This means that the error will not be handled. In this way, whether a constructor successfully creates an object is not determined by returning it. In fact, although the constructor of C++ cannot return, there is a way to judge whether the memory allocation is successful. This method is a mechanism built into the language to deal with emergencies. A predetermined function pointer new-handler can be set as a user-defined function to handle the failure of the new operator. This function can do anything, including setting an error flag, reapplying for memory, quitting the program or throwing an exception. You can safely use the new handler built into the system. The best way to get the constructor to signal an error is to throw an exception. Throwing an exception in the constructor will clear all objects created and allocated memory before the error occurs.

If the constructor fails and exception handling is used, it may be a better idea to initialize in another function. In this way, programmers can safely construct objects and get a reasonable pointer. Then, call initialization function. If initialization fails, the object is cleared directly. 3. Constructors cannot be declared static.

In C++, every class object has a copy of the class data member. However, static members are not like this, but all objects * * * enjoy a static member. Static functions are operations that act on classes rather than objects. You can call a static function using the class name and the operation control operator. One exception is the constructor, because it violates the concept of object-oriented.

A similar phenomenon is the static object, which is initialized at the beginning of the program (before the main () function). The following code explains this situation. MyClass static_object(88,9 1); Hollow strip ()

{

if(static _ object . count()& gt; 14) {

...

}

In this example, static variables are initialized at the beginning. Usually these objects consist of two parts. The first part is the data segment, and static variables are read into the global data segment. The second part is the static initialization function, which is called before the main () function. We found that some compilers did not check the reliability of initialization. So you get an uninitialized object. The solution is to write an encapsulated function and put all references to static objects in the call of this function. The above example should be rewritten like this. Static myclass * static _ object = 0; My class *

getStaticObject()

{

If (! Static _ Object)

Static object =

New myclass (87,92);

Returns static _ object.

} Hollow bar ()

{

if(getStaticObject()-& gt; count()& gt; 15)

{

...

}

}

4. The constructor cannot be a virtual function.

Virtual constructors mean that programmers can create objects without knowing their exact types before running. Virtual constructor is impossible to realize in C++. The most common place to encounter this situation is when I/O is implemented on an object. Even if enough internal information of the class is given in the file, we must try to instantiate the corresponding class. However, experienced C++ programmers will have other ways to simulate virtual constructors.

To simulate a virtual function, you need to specify the constructor to call when creating an object. The standard method is to call virtual member functions. Unfortunately, C++ does not support virtual constructors syntactically. In order to avoid this limitation, some ready-made methods can determine the object of the component at runtime. These are equivalent to virtual constructors, but this is something that does not exist in C++.

The first method is to use switch or if-else selection statement to realize the selection manually. In the following example, the type_info construct based on the standard library is selected, which is supported by opening the runtime type information. But you can also implement RTTI class library through virtual function.

{

Public:

Virtual constchar * get _ type _ id () const;

Static Foundation * Generate Object

(const char * type _ name);

}; const char * Base::get _ type _ id()const

{

Returns typeid(*this). raw _ name();

} class Child 1: public Base

{

}; Class Child2: common foundation

{

}; Base* Base::make_object (constant char* type name)

{

if (strcmp(type_name,

typeid(Child 1)。 raw_name()) == 0)

Returns a new child1;

else if (strcmp(type_name,typeid

(Child2)。 raw_name()) == 0)

Return the new Child2.

other

{

Throw an exception

("Unrecognized type name passed");

Returns 0X00// for null value.

}

}

This implementation is very simple, it requires the programmer to save a table containing all classes in main_object. This breaks the encapsulation of the base class because the base class must know its subclasses. Secretary hodgepodge network