You get a bonus - 1 coin for daily activity. Now you have 1 coin

1.3.Constructor and destructor

Lecture



The disadvantage of the previously discussed classes is the lack of automatic initialization of the created objects. For each newly created object, it was necessary to call a function of type set (as for the class complex), or to explicitly assign values ​​to the object data. However, to initialize objects of a class, you can explicitly include a special component function in its definition, called a constructor . The constructor definition format is as follows.

class_name (list_of_parameters) {designer_body_ operators};

The name of this component function according to the rules of the C ++ language must match the name of the class. Such a function is automatically called when it is defined or allocated in memory using the operator new of each class object.

For example:

сomplex (double re1 = 0.0, double im1 = 0.0) {re = re1; im = im1;}

The constructor allocates memory for the object and initializes the data members of the class.

The designer has a number of features:

· For a constructor, the type of the return value is not determined. Even the void type is not valid.

· A pointer to a constructor cannot be determined and therefore it is impossible to get the address of the constructor.

· Constructors are not inherited.

· Constructors cannot be described with the keywords virtual, static, const, mutuable, valatile.

A constructor always exists for any class, and if it is not defined explicitly, it is created automatically. By default, a parameterless constructor and a copy constructor are created. If the constructor is explicitly described, then a default constructor is not created. By default, constructors are created publicly.

There can be several constructors in a class, but only one with default values ​​for parameters. Overloading is most often used to pass arguments to the constructor for initializing member data of a class. A constructor parameter cannot be its own class, but may be a reference to it (T &). Without an explicit indication of the programmer, the constructor is always automatically called when defining (creating) an object. In this case, the constructor without parameters is called. To explicitly call a constructor, two forms are used:

class_name object_name (actual_parameters);

class_name (actual_parameters);

The first form is allowed only with a non-empty list of actual parameters. It provides for calling the constructor when defining a new object of this class:

complex ss (5.9,0.15);

The second form of the call leads to the creation of an object with no name:

complex ss = complex (5.9,0.15);

There are two ways to initialize object data using a constructor. Earlier, we considered the first method, namely the transfer of parameter values ​​to the body of the constructor. The second method involves the use of a list of initializers of this class. This list is placed between the parameter list and the body of the constructor. Each list initializer refers to a specific component and has the form

datname (expression)

Example 1.3.1

class A

{

int i; float e; char c;

public:

A (int ii, float ee, char cc): i (8), e (i * ee + ii), s (cc) {}

. . .

};

 

Example 1.3.2

Example 1.3.2

// Class “character string”.

#include <string.h>

#include <iostream.h>

class string

{

char * ch; // pointer to text string

int len; // text line length

public:

// constructors

// creates an object - an empty string

string (int N = 80): len (0) {ch = new char [N + 1]; ch [0] = '\ 0';}

// creates an object at the specified string

string (const char * arch) {len = strlen (arch);

ch = new char [len + 1];

strcpy (ch, arch);}

// component functions

// returns a reference to the length of the string

int & len_str (void) {return len;}

 

// returns a pointer to a string

char * str (void) {return ch;}

. . .

};

Here the string class has two constructors - overloaded functions.

By default, a copy constructor of the form T :: T (const T &) is also created, where T is the name of the class. The copy constructor is invoked whenever a copy is made of objects belonging to a class. In particular, it is called:

a) when the object is passed to the function by value;

b) when constructing a temporary object as the return value of the function;

c) when using an object to initialize another object.

If the class does not explicitly contain a specific copy constructor, then when one of these three situations occurs, a bit-wise copy of the object is performed. Bitmap copying is not adequate in all cases. For such cases, it is necessary to define your own copy constructor. For example, create two string objects.

string s1 (“this is a string”);

string s2 = s1;

Here, the s2 object is initialized by the s1 object by calling the copy constructor, created by the default compiler. As a result, these objects have the same value in the ch fields, that is, these fields indicate the same memory area. As a result, if you delete the s1 object, the area occupied by the string will be freed, but the s2 object also needs it. To avoid such errors, we define our own copy constructor.

string (const string & st)

{len = strlen (st.len);

ch = new char [len + 1];

strcpy (ch, st.ch); }

A constructor with one argument can perform an implicit conversion of the type of its argument to the class type of the constructor.

For example:

class complex

{double re, im;

complex (double r): re (r), im (0) {}

...

};

This constructor implements the representation of the real axis in the complex plane.

You can call this constructor in the traditional way.

complex b (5);

But you can call him and so

complex b = 5;

Here it is necessary to convert a scalar value (type of the constructor argument) to the complex type. This is done by calling the constructor with one parameter. Therefore, a constructor that has one argument does not need to be called explicitly, but you can simply write complex b = 5, which means complex b = complex (3).

User-defined conversion is implicitly applied if it is unique. For example,

class demo {

demo (char);

demo (long);

demo (char *);

demo (int *);

...}

Here, in

demo a = 3;

ambiguity: call demo (char)? or demo (long)?

And in demo a = 0; also ambiguity: call demo (char *), or demo (int *), or demo (char), or demo (int)?

In some cases, you need to specify a constructor that can only be called explicitly. For example,

class string {

char * ch;

int len;

public:

string (int size) {

len = size; ch = new [len + 1]; ch [0] = '\ 0';

};

In this case, an implicit conversion may result in an error. In the case of string, s = 'a'; a string of length int ('a') is created. This is hardly what we wanted.

Implicit conversion can be suppressed by declaring a constructor with the explicit modifier . In this case, the constructor will be called only explicitly. In particular, where the copy constructor is basically necessary, the explicit constructor will not be called implicitly. For example:

class string {

char * ch;

int len;

public:

explicit string (int size);

string (const char * ch);

};

string s1 = 'a'; // Error, no explicit char to string conversion

string s2 (10); // Correct, the string to store 10 characters is an explicit // call to the constructor

string s3 = 10; // Error, no explicit int to string conversion

string s4 = string (10); // That's right, the constructor is called explicitly.

string s5 = ”string”; // Correct, implicit constructor call // s5 = string (“string”)

You can create an array of objects, but the corresponding class should have a default constructor (without parameters).

This is due to the fact that when declaring an array of objects, it is impossible to determine the parameters for the constructors of these objects and the only way to call constructors is to pass them the default parameters.

An array of objects can be initialized either automatically by the default constructor, or by explicitly assigning values ​​to each element of the array.

class demo {

int x;

public:

demo () {x = 0;}

demo (int i) {x = i;}

};

void main () {

class demo a [20]; // call the constructor without parameters (by default)

class demo b [2] = {demo (10), demo (100)}; // explicit assignment

When declaring an array of objects, it is impossible to determine the parameters for the constructors of these objects and the only way to call constructors is to transfer the default parameters to them. Thus, in order to create an array of objects, the corresponding class must have a default constructor. You can reduce the number of constructors if you specify a constructor with default arguments. He will be the default constructors.

Dynamic memory allocation for an object makes it necessary to free this memory when an object is destroyed. For example, if an object is formed as local inside a block, then it is advisable that when the block exits, when the object ceases to exist, the memory allocated for it is returned. It is desirable that the release of memory occurs automatically. Such an opportunity is provided by a special class component - the class destructor . Its format is:

~ class_name () {destructor body_ operators};

The name of the destructor coincides with the name of its class, but is preceded by the symbol “~” (tilde).

The destructor has no parameters and no return value. The call to the destructor is performed implicitly (automatically) as soon as the class object is destroyed.

For example, when going outside the definition domain or when calling the delete operator for a pointer to an object.

string * p = new string (“string”);

delete p;

If the destructor is not explicitly defined in the class, the compiler generates a default destructor that simply frees the memory occupied by the object data. In cases where it is necessary to release other memory objects, for example, the area pointed to by ch in the string object, it is necessary to define the destructor explicitly: ~ string () {delete [] ch;}

As well as for the constructor, the pointer to the destructor cannot be defined.


Comments


To leave a comment
If you have any suggestion, idea, thanks or comment, feel free to write. We really value feedback and are glad to hear your opinion.
To reply

C ++ (C plus plus)

Terms: C ++ (C plus plus)