On the unreasonable design of C constructor: Zhang Yan Published: 2001/03/20
Thesis:
In C , the constructor is a special function called when building an object, and its purpose is to initialize the object, so that the object can be in a reasonable state. However, the design of the constructor is not perfect, and even some unreasonable features. This article explores these issues and proposes some solutions.
text:
On the unreasonable design in the C constructor in C , the constructor is a special function called when the component object is called, and its purpose is to initialize the object, so that the object can be in a reasonable status. However, the design of the constructor is not perfect, and even some unreasonable features. For example, the limited constructor name is the same as the name of the class. These features are worth noting when constructing the C compiler. Also, these features should be avoided when the standard revision of the C in the future or to develop other object-oriented design languages. Some solutions are also proposed here. In C , any class has a (at least one) constructor, even when there is no constructor being declared. When the object is declared, these constructors will be called when they are generated. The constructor has made many invisible work, even if there is no code in the constructor, these work includes initializing the memory allocation and by assigning values. The name of the constructor must be the same as the name of the class, but there are many different overloaded versions to provide, through the parameter type to distinguish the version of the constructor. The constructor can be called via the user code, or if the code does not exist, it is implicitly inserted by the compiler. Of course, explicitly pass the code call is a recommended method, because the effect of implicit calls may not be what we expect, especially in processing dynamic memory allocation. The code calls the unique constructor by parameters. The constructor has no return value, although the statement can be returned in the function body. Each constructor can instantiate an object in a different manner because each class has a constructor, at least the default constructor, so each object is used to use the constructor before use. The call to the constructor is shown in Figure 1. Figure 1. The Activities Involved in The Execution of a Constructor Because the constructor is a function, his visibility is nothing more than three kinds of public, private, protected. Typically, constructor is declared as a public type. If the constructor is declared as a private or protected, an instantiation of the object is limited. This is effective in preventing classes from being instantiated by others. The constructor can have any C statement, for example, a print statement, can be added to the constructor to indicate the location of the call. The configuration function of the constructor is a variety of types of functions, and the most commonly used default constructor and copy constructor have some unused constructor. The following describes four different constructor. 1. The default constructor default constructor is a function without parameters. In addition, the default constructor can also be declared in the parameter list in the parameter list. The scope of the default constructor is to initialize the object to the default state. If there is no explicit definition constructor in the class, the compiler will automatically create one, this implicitly created constructor is very similar to an empty constructor. In addition to what works outside the instance of the object, he does not do. In many cases, the default constructor will be automatically called, for example, when an object is declared, it will cause a call to the default constructor. 2, copy constructor copy constructor, often referred to as X (X &), is a special constructor that is called by compiler to complete components and initialization based on other objects based on the same class. Its unique parameter (reference to the object) is invigible (because it is const type). This function is often transmitted and returned by the value of the user-defined type during function call. Copy constructor To call the copy constructor and member function of the base class. If possible, it will be called with a constant mode, alternatively, can also be called in a very square manner.
In C , the following three objects need to be copied. Therefore, the copy constructor will be called. 1). An object is incorporated into the function body 2 in a value. An object returns 3 from the function in a value-delivered manner). An object requires a copy of the constructor that is required to initialize the above-mentioned additional objects. If the first two cases do not use a copy constructor, it will cause a pointer to point to the memory space that has been deleted. For the third case, the different meaning of initialization and assignment is the reason for the constructor call. In fact, the copy constructor is implemented by the ordinary constructor and assignment operation. There are a lot of reference materials that describe the copy constructor and the assignment operator. The copy constructor cannot change the object it referenced, whose reasons are as follows: When an object passes a function in the way, the copy constructor is automatically called to generate the object in the function. If an object is incorporated into your own copy constructor, its copy constructor will be called to copy this object such that the copy can be transferred to its own copy constructor, which can cause an infinite loop. In addition to implicit calls when the object is incorporated, the copy constructor is also called when the object is returned. In other words, you return it from the function that is just a copy of the object. But the same, the copy constructor is called correctly, you don't have to worry. If there is no explicit declaration in the class a copy constructor, then the compiler will make a function to make a function between the object to make a bit copy (bitwise copy). This implicit copy constructor is simplely associated with all class members. Many authors will mention this default copy constructor. Note that this implicit copy constructor and explicitly declared copy constructor differ in the association method for members. The explicit statement of the copy constructor is only the default constructor of the instantiated class member unless another constructor is called when the class is initialized or in the constructive list. The copy constructor is a more efficient program because it changes the parameter list of the constructor when it is used to construct an object. The design copy constructor is a good style, even if the compilation system is provided to help you apply for a memory default copy constructor. In fact, the default copy constructor can cope with many situations. 3. User-defined constructor user-defined constructor allows objects to be initialized simultaneously when they are defined. This constructor can have any type of parameters. A user-defined and other type constructor is reflected in class mystring: class mystring {... public: mystring (); // default constructor mystring (mystring & src) // CONSTRUCTOR MYSTRING (Char * SCR ); // coercion constructor myString (CHAR SCR [], SIZE_T LEN; // user-defined constructor}; 4, forced constructive function C , a constructor with only one parameter can be declared for type conversion. Forced construct a function of a type conversion (implicitly or explicit) that is performed 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 establish a temporary example to replace an instance of a parameter type. Note that the standard newly added C keywords explicit is used to disable implicit type conversions. However, this feature has not been supported by all compiler.
Here is an example of a forced constructor: Class a {public: a (int) {}}; void f (a) {} void g () {a my_object = 17; A A2 = A (57); A A3 ( 64); MY_Object = 67; f (77);} A my_Object = 17; this declaration means that the A (int) constructor is called to generate an object from the integer variable. Such a constructor is a forced constructor. The universal characteristics are the unreasonable design of some C constructors, of course, there may be some other unreasonable. However, in most cases, we still have to deal with these features, we have to explain one by one. 1. The constructor can be inline, but don't do this, most member functions can be added to the "inline" keyword, and the constructor is no exception, but don't do this! A constructor defined as the inline is as follows: Class X {........ public: x (int);::}; inline x :: x (int) {...} on top In the code, the function is not inserted into a single entity but is inserted into the program code. This will be efficient for only one or two statements, because there is no call for the function here. The risk of using the inline constructor can be reflected in the definition of a static inner built-in function. In this case, the static constructor should be only called once. However, if the header file contains a static inline structure and is included by other units, the function generates multiple copies. This way, all function copies are called when the program is started, not a copy of the program to call. The root cause is that the static function is a real object under functional camouflage. One thing that should be keen is that inline is a suggestion rather than forced, the compiler produces an inline code. This means that inline is different from the compiler of the implementation, it may bring a lot of differences. On the other hand, in the inline function may include something more than code. The constructor is declared as inline, all constructor of the object constructor, and the construction function of the base class need to be called. These calls are hidden in the constructor. This may create a large inline function segment, so the inline constructor is not recommended. 2, the constructor does not have any return type to specify a return type for a constructor is an error, as this will introduce the address of the constructor. This means that an error will not be handled. In this way, a constructor successfully created an object will not be determined by returning. In fact, although the C constructor cannot return, there is a method to determine if the memory allocation is successfully performed. This method is to build a mechanism for processing emergencies within the language. A predetermined function pointer new-handler, which can be set to a function of user customized to the new operator failed, which can make any action, including setting an error flag, reapplying the memory, exiting the program or throwing an exception. You can use the New-handler built in the system. The best way to make the constructor make an error signal, it is to throw an exception. Throw an exception in the constructor to clear any objects and allocated memory created before the error. If the construct function fails to use exception handling, then initialization in another function may be a better idea. In this way, programmers can safely component objects and get a reasonable pointer. Then, the initialization function is called. If initialization failed, the object is directly cleared. 3. The constructor cannot be declared in Static C , and each class has a copy of the class data member. However, static members do not have this but all objects share a static member. The static function is actions acting on the class, not on the object.
You can call a static function with a class name and a role control operator. One of this is the constructor because it violates the object-oriented concept. A similar phenomenon about these is a static object, and the initialization of the static object is performed in the beginning of the program (before the main () function). The following code explains this situation. Myclass static_object (88, 91); void bar () {if (static_Object.count ()> 14) {...}} In this example, the static variable is initialized at the beginning. Usually these objects are composed of two parts. The first part is the data segment, and the static variable is read into the global data segment. The second part is a static initialization function, called before the main () function. We found that some compilers do not check the reliability of the initialization. So you get an uninitialized object. The solution is to write a package function, put all the references of all static objects in the call of this function, the above example should be rewritten. static MyClass * static_object = 0; MyClass * getStaticObject () {if (static_object!) static_object = new MyClass (87, 92); return static_object;} void bar () {if (getStaticObject () -> count ()> 15) {...}} 4, the constructor cannot be a virtual function fiction function means that the programmer can create an object without knowing the exact type of the object before run. The fiction function is not possible in C . The most often encountered this situation is when I / O is implemented on the object. Even if the internal information of the class is given in the file, it must also find a method to instantiate the corresponding class. However, experienced C programmers have other ways to simulate the fictional build function. The simulated virtual function needs to specify the constructor when the object is created, and the standard method is to call the virtual member function. Unfortunately, C does not support the fictional manufacturing function on the syntax. In order to bypass this limit, some of the ready-made methods can determine the object of the component at runtime. These are equivalent to the fiction, but this is something that does not exist at C . The first method is to manually implement the selection with the Switch or IF-ELSE selection statement. In the following example, the selection is based on the Type_info constructor of the standard library, by opening the runtime type information support.
But you can also be achieved by virtual functions RTTI class Base {public: virtual const char * get_type_id () const; staticBase * make_object (const char * type_name);}; const char * Base :: get_type_id () const {return typeid ( * this) .raw_name ();} class Child1: public Base {}; class Child2: public Base {}; Base * Base :: make_object (const char * type_name) {if (strcmp (type_name, typeid (Child1) .raw_name () == 0) Return New Child1; Else IF (strcmp (Type_name, TypeId (child2) .raw_name ()) == 0) Return New Child2; Else {Throw Exception ("Unrecognized Type Name Pass); return 0x00 The implementation is very straightforward, it requires a programmer to save a list of all classes in the main_Object. This disrupts the encapsulation of the base class, as the base class must know his own subclasses. A more object-oriented method class solves the fictional function called the specimen instance. Its basic idea is that some overall instances are generated in the program.
These instances are only virtually virtually configured to create functions: class base {public: staticbase * make_object (const char * typename) {if (! Exemplars.empty ()) {base * end = * (ExemPlars.end ()); List
More specifically, when the first layer of the inherited level is constructed, all the constructors of all base classes are called before the derived base class, and an example, look at the following code: #include
This bit copy is no effect on the class containing the pointer to other objects (see Figure 2). When a class containing a pointer is incorporated into a function, the object is copied, including the address of the pointer, and the scope of the new object is this function. At the end of the function, unfortunately, the destructive function should destroy this object. Therefore, the pointer of the object is deleted. This results in a pointer to the original object to point to an empty memory area - an error. There is also a similar situation when the function returns. Figure 2. The Automatic Copy Constructor That Makes A Bitwise Copy of the Class. This problem can be simplified by defining a copy constructor containing memory applications in the class, which is called a deep copy, which is allocated in the heap. Give each object. 8, the compiler can implicitly specify the forced constructor because the compiler can implicitly select the force constructor, you lose the option to call the function. If you need to control, don't declare that only one parameter constructor is required, replaced it, define the Helper function to be responsible for conversion, as follows: #include