C++. Class functions that are declared with a constant (const) ‘this’ pointer and a volatile ‘this’ pointer




Class functions that are declared with a constant (const) ‘this’ pointer and a volatile ‘this’ pointer


Contents


Search other websites:

1. What does the general form of a function declaration look like with the constant ‘this’ pointer?

Declaring a function in a class (for example, the functions MyFun1(), MyFun2()) with the constant pointer ‘this’ has the following general form:

class CMyClass
{
    private:
    // hidden data members and class methods
    // ...

    public:
    // function is declared with the constant pointer this
    return_type MyFun1(parameters) const; // out-of-line
    return_type MyFun2(parameters) const // inline implementation
    {
        // body of function
        // ...
    }
}

// implementation of out-of-line function
return_type CMyClass::MyFun1(parameters) const
{
    // body of MyFun1() function
    // ...
}

where

  • return_type – type that is returned by a function;
  • parameters – parameters that the function receives.

In the above fragment, the CMyClass class declares two functions with the constant pointer ‘this’. Function MyFun1() is implemented outside the class (out-of-line). Function MyFun2() is implemented in the class (inline). Before the body of each function is placed the ‘const’ keyword.

2. What is the essence of the function declaration with constant ‘this’ pointer?

In a function with a constant ‘this’ pointer, the keyword ‘const’ is placed before the function body. This means that the function body has limited usabilities.
It should be noted, that in this case the keyword ‘const’ does not have to do with the value returned by the function. It makes sense only for the ‘this’ pointer used in the function.

If the function is declared with the constant pointer ‘this’, then in the body of the function it is forbidden to change the data of the class. If you try to change the class data, a compilation error will occur.

3. An example that demonstrates the difference between functions with the constant pointer ‘this’ and without it

The difference between a regular function and a function with a constant ‘this’ is clearly visible in the implementation of the following class.
Suppose that the class CRadius is given. This class implements the radius of some object or geometric figure.
In the class are implemented:

  • internal data member radius of type double;
  • the constructor CRadius();
  • the usual function GetRadius(), which increases the radius twice and returns its value;
  • function GetRadius2(), declared with the constant pointer ‘this’. This function returns the value of the internal variable radius.
// class CRadius
class CRadius
{
    double radius;

    public:
    CRadius(void); // class constructor by default

    // Ordinary class member function,
    // for this function is implicitly passed a pointer: CRadius * const this
    double GetRadius(void)
    {
        radius *= 2.0; // allowed
        return radius;
    }

    // A member function of a class, which is declared with a 'const'
    // for this function is passed a pointer: const CRadius * const this
    double GetRadius2(void) const
    {
        //radius = 2.0; // Forbidden! Compilation error
        return radius;
    }
};

If you try to change the value of the internal variable radius in the GetRadius2() function, you will get a compilation error:

Error: 'radius' cannot be modified because it is being accessed through a const object

The keyword const in front of the function body in the class means that the function cannot make any changes to members of the class data.

Using the CRadius class in some code:

CRadius CR;

double d;
d = CR.GetRadius2(); // d = 1.0 - calling of function with constant pointer 'this'
d = CR.GetRadius(); // d = 1.0 - calling an ordinary member function

4. How is the ‘this’ pointer modified, which is passed to the member function, which is declared with the constant pointer ‘this’?

Let the class CRadius be given, in which there is a member function with the constant pointer this:

// CRadius class
class CRadius
{
    double radius;

    public:
    CRadius(void); // class constructor by default

    // Ordinary class member function,
    // for this function is implicitly passed a pointer: CRadius * const this
    double GetRadius(void)
    {
        radius *= 2.0; // allowed
        return radius;
    }

    // A member function of a class, which is declared with a 'const'
    // for this function is passed a pointer: const CRadius * const this
    double GetRadius2(void) const
    {
        //radius = 2.0; // Forbidden! Compilation error
        return radius;
    }
};

The this pointer in the class is invisible, it is implicitly passed to class functions. This means that when you try to explicitly declare ‘this’ pointer in the class, the compiler will generate an error.
For a regular member function of the GetRadius() class, the ‘this’ pointer is passed implicitly as:

CRadius * const this;

For the member function GetRadius2() the invisible ‘this’ pointer is passed with the keyword const:

// a modified this pointer
const CRadius * const this;

Row

const CRadius

means that an object of type CRadius is a constant object. Therefore, you can not change object values in the body of the GetRadius2() function. So, you can not change the values of the internal members-data of class in the function GetRadius2(). Attempting to change the values of the inner member of data in the body of the GetRadius2() function will cause a compilation error.

5. Why use the functions of a class with a constant pointer ‘this’?

Functions with a constant ‘this’ pointer are advisable to use in cases when it is necessary that the member function of the base class is not accidentally redefined in the derived classes. In this case, the constant pointer ‘this’ serves to protect the data of the base class from accidental changes in the derived classes.






6. What happens if the const keyword is placed before the function name, and not before the function body?

This is important. In this case, the function returns a constant value. But you can change the internal data of the class in the body of the function. The ‘const’ keyword before the function name refers to the value returned by the function. The const keyword before the function body refers to ‘this’ pointer.

7. Is it possible to declare the keyword ‘const’ for static member functions?

Declaring a static member function with the const keyword does not make sense. When you call a static member function, the invisible ‘this’ pointer is not passed to this function. If you try to declare a static member function with a constant ‘this’ pointer, the compiler will generate an error

... modifiers not allowed on static members functions

8. What is the general form of declaring a member function with a volatile this pointer? The ‘volatile’ keyword

In order to declare a member function with a volatile ‘this’ pointer, the keyword ‘volatile’ is used.
The general form of declaring a function with a volatile ‘this’ pointer in the class is approximately as follows:

class CMyClass
{
    // hidden data members and class methods
    // ...

    public:
    // public data members and class methods
    // member function with a volatile 'this' pointer
    return_type MyFun1(parameters) volatile; // out-of-line
    return_type MyFun2(parameters) volatile // inline
    {
        // the body of function
        // ...
    }
}

// implementation of out-of-line function
return_type CMyClass::MyFun1() volatile
{
    // the body of MyFun1() function
    // ...
}

where

  • return_type – type that is returned by a function;
  • parameters – parameters that the function receives.

In the above fragment, in the CMyClass class, two functions with a volatile pointer ‘this’ are declared. Function MyFun1() is implemented outside the class (out-of-line). Function MyFun2() is implemented in class (inline). Before the body of each function is the keyword ‘volatile’.

9. In which cases is it appropriate to declare a function with a volatile pointer ‘this’?

The declaration of a function as volatile is advisable to use in cases when it is necessary to process a class object with different processes, to which one can include:

  • object processing by the processor;
  • processing with background applications;
  • processing with the help of interrupt processing programs.

10. What does the use of the ‘volatile’ keyword for a member function of a class give?

The member function of a class that is declared with the ‘volatile’ keyword is treated differently by the compiler in different cases. For such functions, the compiler disables some types of optimization, depending on the type of the declared object. The member functions of the class that are declared with the volatile keyword can be used for both automatic objects and non-constant (volatile) objects.

For constant objects, the use of functions with a volatile pointer is prohibited. Again, it all depends on the settings and implementation of the compiler.

11. An example of using member functions with a volatile ‘this’ pointer

Let the class CRadius be given. In the class are implemented:

  • the internal data member – ‘radius’;
  • the constructor CRadius();
  • a regular member function GetRadius() of the class;
  • two member functions with a volatile ‘this’ pointer: GetRadius2() and SetRadius().
// class CRadius
class CRadius
{
    double radius;

    public:
    CRadius(void); // class constructor by default

    // Ordinary member-function of class,
    // to this function is implicitly passed to: CRadius * const this
    double GetRadius(void)
    {
        return radius;
    }

    // A member function of a class, which is declared with 'volatile'
    // to this function is passed to: volatile CRadius * const this
    double GetRadius2(void) volatile
    {
        return radius;
    }

    // A member function of a class declared with 'volatile' keyword
    void SetRadius(double r) volatile
    {
        radius = r;
    }
};

Using a class in another program code

CRadius CR1; // automatic object
volatile CRadius CR2; // volatile object

double d;

// automatic object
CR1.SetRadius(5.5);
d = CR1.GetRadius2(); // d = 5.5

// volatile object
CR2.SetRadius(6.7);
d = CR2.GetRadius2(); // d = 6.7

As you can see from the program code, member functions with a volatile pointer this can be used for automatic and non-persistent objects. In this case, the compiler includes various types of optimization, depending on the type of object.


Related topics