C++. Classes. Part 1. The concept of class. Declaring a data type “class”. The object of the class. Classes in the CLR. Encapsulation of data in a class

C++. Classes. Part 1. The concept of class. Class declaration. The object of the class. Classes in the CLR. Encapsulation of data in a class


Contents


1. Basic concepts of object-oriented programming. Classes and objects

In the C++ programming language, the concept of “class” is the basis of object-oriented programming (OOP). Object-oriented programming arose as an improvement to procedural-oriented programming. At one time, procedure-oriented programming no longer provided the necessary quality of writing large software systems.

The programs were divided (structured) into modules. There was a repeatability of program code in different modules (parts) of the program. Testing was complicated. The reliability of the program was decrease.

At the heart of the OOP are the concepts of “object” and “class”. In an programming language, an object is a variable of type “class”. The class declares the data and methods (functions) to be used by the object of this class. Each class describes a logically completed unit of the program. Encapsulation of data and methods of processing them within the class allows improving the structuring of software systems. This in turn reduces the risk of “invisible” logical errors. The use of heredity and polymorphism in classes makes it possible to avoid the repetition of program code and conveniently organize complex calls of methods that are combined into a list.

The class defines the format (description) of some data and the work (behavior) over this data. From a class declaration, you can get a different number of class objects (class variables). Each object of the class is determined by the specific (at the moment) value of the internal data (variables), which is called the state of the object.

The class declares data (internal variables, properties) and methods (functions) that operate on these data.

A class can be inherited from other classes of upper levels. This means that a class can use part of the code of other classes of upper levels.

Also, a class can be a parent for other classes that inherit its program code.

 

2. What kinds of C++ classes can be implemented in CLR?

The CLR (Common Language Runtime) supports two kinds of classes:

  • unmanaged classes. To allocate memory for objects of such classes, unmanaged pointers (*) and the new operation can be used;
  • managed classes. To allocate memory in such classes, you can use managed pointers (^) and the gcnew operation.

This topic highlights the features of using unmanaged (*) classes.

Examples that demonstrate the features of use and the difference between managed (^) and unmanaged (*) classes are described in more detail in the topic:

 

3. The general form of an unmanaged-class declaration. The keyword “class”

In the simplest case (without inheritance), the general form of the unmanaged class declaration is as follows

class class_name
{
    private:
    // hidden (closed) data and methods (functions)
    // ...

    public:
    // open data and methods
    // ...

    protected:
    // protected data and methods
    // ...
};

where

  • class_name – directly the name of the new data type “class”. This name is used when creating class objects.

The keyword ‘class’ reports that a new class (data type) is declared. Inside the class, the members of the class are declared: data and methods. The keyword ‘private’ defines the members of the class that must be closed from external methods declared outside the class, as well as class objects. Data members declared with the keyword ‘private’ are only available to other members of this class.

The keyword ‘public’ defines the public data (variables) and methods (functions) of the class.

The keyword ‘protected’ defines protected data and class methods that are:

  • accessible to the methods inherited from this class;
  • inaccessible to the methods implemented in other parts of the program;
  • inaccessible for class objects.

Within the class definition, the sections ‘private’, ‘protected’, ‘public’ can follow in any order and in any number. For example:

class MyClass
{
    // section 'private' by default
    // ...

    public:
    // the 'public' section
    // ...

    protected:
    // the 'protected' section
    // ...

    private:
    // again section 'private'
    // ...

    public:
    // again section 'public'
    // ...
};

 

4. What does the term “data encapsulation” mean in a class?

The term “data encapsulation” means that for members of a class, you can set the degree of accessibility from other parts of the code. Thus, the notion of data hiding in the class arises. Encapsulation provides an improvement in the reliability of data storing in the class by entering the additional methods for verifying this data to allowable values. As a rule, access to hidden data in the class is not directly, but through calls to special accessors or class properties. Directly, the data is placed in a hidden section of the class, and the methods of access to the data posted on the public section of the class.

The classic C++ language allows you to set access to class members using three specifiers: private, protected, public.

 

5. What types of access can class members have? What are the differences between the members of the class declared with the keywords ‘private’, ‘protected’, ‘public’?

Members of a class can have three basic types of access, which are determined by the corresponding keywords:

  • private – members of the class are hidden. This means that only class methods have access to them. private-members of the class are inaccessible from inherited classes and objects of this class;
  • protected – members of the class are protected. This means that methods of this class and methods of inherited classes have access to protected members. protected-members of the class are inaccessible to objects of this class;
  • public – members of the class are accessible to all methods and objects from all other parts of the program code.

 

6. Can a class, when it is declared, contain only data and do not contain methods?

A class can be declared without methods. These classes contain only data. In this case, they differ little from structures. To access data in a class that does not contain methods, you need to declare this data in the ‘public’ section. Classes without methods are almost never used. If you declare the data in the ‘private’ section, you will not be able to access the data members of the class.

Example. In this example, a class with no methods is declared that implements operations on the date. The class contains internal variables (data), which are:

  • month day;
  • month;
  • year.
class CMyDate
{
    public:
    int day; // month day
    int month; // month
    int year; // year
};

A snippet of code that demonstrates working with the CMyDate class

// declare an object of class MyDate
CMyDate D;

// fill in the values of the class fields
D.day = 20;
D.month = 02;
D.year = 2002;

int t = D.year; // t = 2002
t = D.month; // t = 2

 

7. An example of an empty class declaration

A class can be declared without data and without methods. For example, below is declared a class which does not contain any data or methods.

// class does not contain any data or methods
class NoData
{

};

An object of this class is also created.

NoData nd; // NoData class object

It is understood that this class has a specified use. It is advisable to create an empty class in cases when during the creation of a large project it is necessary to protest its earlier (initial) version, in which some classes have not yet been developed and implemented. Instead of a real class, an empty class is indicated – a stub. This empty class is designed for the needs of the future project in such a way that the compiler does not produce error messages and you could protest that part of the code that has already been written. In this case, the name of the empty class is chosen as it should be in the future project.

 

8. An example of a class containing methods (functions)

The main advantages of classes are found in the presence of methods – members of the class. With the help of data access methods in classes it is possible to conveniently:

  • initialize data;
  • verify the correctness of internal data when they are set;
  • implement various options for data conversion;
  • allocate memory for complex data types implemented in classes;
  • perform a variety of calculations on the data.

Example. Modification of CMyDate class. A class that describes the date and operations on it. Access operations for class members are implemented using appropriate methods. The data itself are implemented in the private section.

The program code of the class

class CMyDate
{
    int day;
    int month;
    int year;

    public:
    void SetDate(int d, int m, int y); //
    int GetDay(void); // returns day of the month
    int GetMonth(void); // returns the month
    int GetYear(void); // returns the year
};

Implementing the methods of the class SetDate(), GetDay(), GetMonth(), GetYear()

// Set a new date
void CMyDate::SetDate(int d, int m, int y)
{
    day = d;
    month = m;
    year = y;
}
// get the day number
int CMyDate::GetDay(void)
{
    return day;
}

// get the month number
int CMyDate::GetMonth(void)
{
    return month;
}

// get the year
int CMyDate::GetYear(void)
{
    return year;
}

Using class methods from other program code (for example, an event handler in applications such as Windows Forms)

// class object
CMyDate MD;

// set the date to 20.02.2002
MD.SetDate(20, 2, 2002);

// get the date
int t;
t = MD.GetDay(); // t = 20
t = MD.GetMonth(); // t = 2
t = MD.GetYear(); // t = 2002

 

9. In which parts of the class and program can you declare the implementation of class methods?

The implementation of class methods can be declared in the class and outside the class.

For example. The following code declares the class CMyTime. The class contains two methods SetTime1() and SetTime2(), which perform the same work: they set a new time. The implementation of the SetTime1() method is in the CMyTime class. In the class, only the prototype of the SetTime2() method is declared.

class CMyTime
{
    private:
    int sec; // second
    int min; // minute
    int hour; // time

    public:
    // declaration and implementation of the method within the class
    void SetTime1(int h, int m, int s)
    {
        // implementation
        hour = h;
        min = m;
        sec = s;
    }


    // only the declaration (prototype) of the method (the SetTime2 method is a member of the class)
    void SetTime2(int h, int m, int s); // the implementation of the method is outside the class
};

// implementation of the SetTime2() method outside the class
void CMyTime::SetTime2(int h, int m, int s)
{
    hour = h;
    min = m;
    sec = s;
}

The body of a method that is implemented outside the class can be in another module. Typically, in the Microsoft Visual Studio system, this module has a .cpp extension. The class itself is described in the module with the extension *.h.

 

10. What purpose does the scope extension operator ‘::’ have?

The program code of member methods can be described in the class itself and beyond. If you need to develop a method code that is a member of a class, you use the scope extension operator “::” to do this. The “::” operator specifies the name of the class member along with the class name in which it is implemented.

 

11. What is a class object? What are the differences between a class object and a class declaration? Declaring a class object

A class declaration is a description of a data type format. This data type “class” describes the data and methods that operate on these data. Declaring a class is just an declaration. In this case, the memory for the class is not allocated.

Memory is allocated only when the class is used to create the object. This process is also called creating an instance of a class, which is the physical essence of the class.

Declaring a class object (instance) is no different from declaring a variable:

class_name object_name;

With the name object_name, you can access the public members of the class. This is done using the ‘ . ‘ character.

It is also possible to declare a pointer to a class. If this is an unmanaged-class, then the declaration looks like this:

class_name * object_name;

After such declaration, it is necessary to allocate memory for the object class using the ‘new’ operator. Access to data by the pointer is performed using the combination of the characters ‘->’ exactly as in the case of structures.

For example. Declaration of the ‘Worker’ class, which describes methods and data about the employee of the enterprise.

class Worker
{
    private:
    // private-members of class 'Worker'
    // ...

    public:
    // public-members of class 'Worker'
    // ...
};

A class object is a variable of type “class”. When a class object is declared, the memory for this object (variable) is allocated. For example, for the Worker class, you can write the following code

Worker w1; // object of class Worker, memory for object data is allocated

From the object, you can only access the public members of the class. This can be done with the symbol ‘ . ‘ or access by the pointer ‘->’:

w1.SetName("Johnson J."); // 'public' method call
Worker * w2; // pointer to class 'Worker'
w2 = new Worker(); // dynamic allocation of memory for the class
w2->SetName("Jackson M."); // call the public method from the class by pointer

 

12. What type of access do the members of a class have by default in C++?

By default, class members have private access. Therefore, when declaring a class, if you want to specify private members of a class, you can omit this word.

For example, suppose there are class declarations that describe the pixel on the monitor screen.

class CMyPixel
{
    int color; // private section
    int x;
    int y;

    public:
    // public methods
    void SetXYColor(int nx, int ny, int ncolor)
    {
        x = nx; y = ny; color = ncolor;
    }

    int GetX(void) { return x; }
    int GetY(void) { return y; }
    int GetColor(void) { return color; }
};

As you can see, at the beginning of the class declaration, the ‘private’ section is missing. This means that the data members of the class color, x, y are hidden. When creating a class object and directly accessing them, the compiler will generate an error

CMyPixel MP; // declare a class object
// MP.x = 25; - error - "CMyPixel::x - cannot access private member declared in CMyPixel
MP.SetXYColor(25, 15, 2); // that's right

 

13. How can I access private members of a class?

The ‘private’ members of the class are inaccessible. This is the main advantage of encapsulation. To change the values of private-members of a class, use the methods of the class that are declared in the ‘public’ section. In these methods, you can change the values of ‘private’ members. This approach is used to ensure the reliability of storing data in private members. In public methods that have access to private members, you can implement additional validation checks for values.

For example.

Let there be given a class that defines an array of n real numbers. The class contains two ‘private’ data members:

  • n – the number of elements in the array;
  • A – directly array.

Judging from the logic of the problem, in such a class the number of elements of the array can not be less than zero (<0). Therefore, in the SetN() method, which sets the value of n, it is advisable to check for the correctness of the value of n.

The code for the class that demonstrates access to the private members of the class is shown below.

class CMyArray
{
    int n;
    float *A; // an array of type float, the memory for the array is allocated dynamically

    public:
    CMyArray(); // class constructor
    void SetN(int nn); // set new n, reset array A
    int GetN(void); // read n
    void SetAi(int index, float value); // set the new value in A[index]
    float GetAi(int index); // read the value from A[index]
};

// class constructor
CMyArray::CMyArray()
{
    n = 0;
}

// set the new value of n, and set the value of array elements to 0
void CMyArray::SetN(int nn)
{
    if (n>0) delete A; // release the memory, allocated previously for array A
    n = nn;
    A = new float[n]; // allocate memory for n array elements

    // fill in elements of the array to 0 value
    for (int i=0; i<n; i++)
        A[i] = 0;
}

// read n
int CMyArray::GetN(void)
{
    return n;
}

// set the new value in A[index]
void CMyArray::SetAi(int index, float value)
{
    if (n<=0) return;
    if (index > n-1) return;
        A[index] = value;
}

// read the value A[index]
float CMyArray::GetAi(int index)
{
    return (float)A[index];
}

As you can see from the program code, a new element is declared in the class – the class constructor. This is a special method that is used to initialize the members of the class data. More details about the constructors and destructors of the class are described in the topics:

A snippet of using the CMyArray class from another program code:

CMyArray MA; // create a CMyArray class object
int d;
double x;

MA.SetN(15);
d = MA.GetN(); // d = 15

MA.SetAi(3, 2.88);
x = MA.GetAi(3); // x = 2.88
x = MA.GetAi(10); // x = 0

MA.Set(20); // array redefinition
d = MA.GetN(); // d = 20
x = MA.GetAi(3); // x = 0

 


Related topics