Click here to Skip to main content
15,867,453 members
Articles / Programming Languages / C++

Constant Member Functions Are Not Always Constant

Rate me:
Please Sign up or sign in to vote.
3.63/5 (24 votes)
24 May 2012CPOL3 min read 47.8K   194   16   50
In this article, I'm going to explain why the constant member functions aren't always constant, i.e. despite of the fact that a function is declared as constant, it still allows setting or changing data members within the class

Herakleitos

Introduction

Recently, I had a discussion with my friends about constant member functions in C++ (for example void MyClass::foo const {...}) And one of my friends (he is really great at C++) said that if a member function is const-qualified, then we cannot modify any member variables in the scope of this function. Honestly, such a categorical opinion surprised me and I said, "it's not quite right!!" But all the participants in the debate supported my friend's view. This discussion prompted me to write a short article on the topic about how easy it is to modify the data members of your class in a const function of C++

Background

In fact, even one of the most-read books about C++, called "The C++ Programming Language, Third Edition" by Bjarne Stroustrup, says the following:

"10.2.6 Constant Member Functions [class.constmem]

C++
class Date
{
    int d, m, y;
    public :
       int day () const     { return  d; }
       int month () const { return m; }
       int year () const ;
    // ...
};

Note the const after the (empty) argument list in the function declarations. It indicates that these functions do not modify the state of a Date.

Naturally, the compiler will catch accidental attempts to violate this promise. For example:

C++
inline int Date::year () const
{
   return y ++; // error:  attempt to change member value in const function
}

When a const member function is defined outside its class, the const suffix is required:
inline int Date::year () const
{
   return y ; // correct
}

And really, if your code tries to change some data member in a const function (by the above manner), you would get an error. When you develop an application by using Visual C++, you will receive the following message:

       error C3490: <your data member> cannot be modified because it is being accessed through a const object

I don't want to argue with the compiler (and even more so with the genial creator of C++) I only want to show another case ...

From my point of view, the author of the book didn't provide full disclosure of this subject, therefore, many programmers understand this subject insufficiently.

The Solution

I use a slightly different technique than the one showed by B.Stroustrup. My approach here allows you to use an interesting trick. The trick may look quite ugly, but it works ...

C++
class User
{
  public:
	User(unsigned int id, unsigned int age, std::string name) 
		: mID(id) , 
		  mAge(age),
		  mName(name)
	{

	}

	void ChangeMe1 (unsigned int id, unsigned int age, std::string name) const;
	void ChangeMe2 (unsigned int id, unsigned int age, std::string name) const;
	void PrintMyData ();
private:
	unsigned int           mID;
	unsigned int           mAge;
        std::string            mName;
};

//To make changes by the pointer (a synonym on this)
void User::ChangeMe1 (unsigned int id, unsigned int age, std::string name) const
{
	// Here can be used and the old C-style cast to remove the constness, i.e.:
        // User * synonym_of_this =  (User *) this;
        User * synonym_of_this = const_cast<User *>(this);


	synonym_of_this->mID   = id; 
	synonym_of_this->mAge  = age;
	synonym_of_this->mName = name; 
}

//To make changes by creating the reference on this
void User::ChangeMe2 (unsigned int id, unsigned int age, std::string name) const
{
	// Here can be used and the old C-style cast to remove the constness, i.e.:
        // const UserPtr &synonym_of_this =  (User *) this;
        const UserPtr &synonym_of_this = const_cast<User *>(this);


	synonym_of_this->mID   = id; 
	synonym_of_this->mAge  = age;
	synonym_of_this->mName = name;
}

void User::PrintMyData ()
{
	std::cout << "ID = " << this->mID << " Age = " << this->mAge <<  " Name = " << this->mName.c_str() << "\n"; 
}

int main()
{
	User presedent_USA (42,46,"Bill Clinton");
	std::cout << "Now the presedent of USA : " << std::endl;
	presedent_USA.PrintMyData();
	
        std::cout << "\nLet's hold an election..." << std::endl;
	presedent_USA.ChangeMe1(43,54,"George Walker Bush");
	std::cout << "\nNow the presedent of USA : " << std::endl;
	presedent_USA.PrintMyData();

	std::cout << "\nLet's hold an election..." << std::endl;
	presedent_USA.ChangeMe2(44,47,"Barack Hussein Obama 2");
        std::cout << "\nNow the presedent of USA : " << std::endl;
	presedent_USA.PrintMyData();
	std::cout << "\n";

	return 0;
}

As you can be see from the above code example we continue to use the const-qualified function, but after starting the following program:

Image 2

We can see that all members of this class have been changed, i.e. the ChangeMe1, and ChangeMe2 a "const" functions can modify any data members. Apparently the famous greek philosopher Heraclitus was right. In the ChangeMe1 function I used a "workaround" based on accessing data members through a pointer which is a synonym for this. The second solution used in ChangeMe2 is based on creating a reference to this, which behaves also as a synonym for this.

Why is it so important to consider?

  1. The const function can change the data members of class
    (for example, if you deal with scary legacy code and it's necessary to detect the place where some members of a class are changed, then do not ignore the code in the scope of a constant function, because there also may be changes)
  2. If you want to change the data members of a class (for some reason), but it's not possible to change the signature of a method, then you can use the "trick" that I showed. It is important to note that this should be done to resolve problems, but only in very extreme cases. It basically doesn't make any sense to cancel or violate the constancy of constant method, but if you are going to use this "trick", please write detailed comments, to be able to maintain your code. That's all!

History

  • 18nd April 2011: Initial post
  • License

    This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


    Written By
    Software Developer
    Canada Canada
    Mr.Volynsky Alex is a Software Engineer in a leading software company. Alex is skilled in many areas of computer science. He has over 14 years of experience in the design & development of applications using C/C++/STL, Python, Qt, MFC, DirectShow, JavaScript, VBScript, Bash and of course - C#/.NET.

    In addition, Alex is the active member of Intel® Developer Zone (he was awarded by Intel® Green Belt for his active contribution to the Intel Developer Zone community for developers using Intel technology).

    Alex is also interested in the Objective-C development for the iPad/iPhone platforms and he is the developer of the free 15-puzzle game on the App Store.

    Overall, Alex is very easy to work with. He adapts to new systems and technology while performing complete problem definition research.

    His hobbies include yacht racing, photography and reading in multiple genres.
    He is also fascinated by attending computer meetings in general, loves traveling, and also takes pleasure in exercising and relaxing with friends.

    Visit his C++ 11 blog

    Comments and Discussions

     
    QuestionGood Solution, but sometimes this trick gives access violation error in VS2013 compiler Pin
    Tameezuddin24-Oct-17 3:02
    Tameezuddin24-Oct-17 3:02 
    GeneralMy vote of 5 Pin
    mk4you713-Jun-12 5:00
    mk4you713-Jun-12 5:00 
    GeneralRe: My vote of 5 Pin
    Volynsky Alex14-Jun-12 15:04
    professionalVolynsky Alex14-Jun-12 15:04 
    SuggestionMy vote of 5 Pin
    Grigor_I29-May-12 10:13
    Grigor_I29-May-12 10:13 
    GeneralRe: My vote of 5 Pin
    Volynsky Alex3-Jun-12 8:21
    professionalVolynsky Alex3-Jun-12 8:21 
    GeneralThe Const Nazi | Games from Within Pin
    Rolf Kristensen29-May-12 4:05
    Rolf Kristensen29-May-12 4:05 
    GeneralRe: The Const Nazi | Games from Within Pin
    Volynsky Alex3-Jun-12 8:22
    professionalVolynsky Alex3-Jun-12 8:22 
    GeneralMy vote of 5 Pin
    Steph_Iv28-May-12 10:36
    Steph_Iv28-May-12 10:36 
    GeneralRe: My vote of 5 Pin
    Volynsky Alex3-Jun-12 8:23
    professionalVolynsky Alex3-Jun-12 8:23 
    GeneralMy vote of 5 Pin
    EMogilevsky26-May-12 4:21
    EMogilevsky26-May-12 4:21 
    GeneralRe: My vote of 5 Pin
    Volynsky Alex26-May-12 6:59
    professionalVolynsky Alex26-May-12 6:59 
    GeneralMy vote of 5 Pin
    Gerard Forestier24-May-12 22:05
    Gerard Forestier24-May-12 22:05 
    GeneralRe: My vote of 5 Pin
    Volynsky Alex26-May-12 7:00
    professionalVolynsky Alex26-May-12 7:00 
    GeneralMy vote of 3 Pin
    Paul M Watt23-May-12 13:39
    mentorPaul M Watt23-May-12 13:39 
    GeneralRe: My vote of 5 Pin
    Volynsky Alex24-May-12 12:49
    professionalVolynsky Alex24-May-12 12:49 
    GeneralMy vote of 1 Pin
    bitterskittles23-May-12 6:53
    bitterskittles23-May-12 6:53 
    GeneralRe: My vote of 5 Pin
    Volynsky Alex23-May-12 8:35
    professionalVolynsky Alex23-May-12 8:35 
    GeneralRe: My vote of 5 Pin
    Volynsky Alex24-May-12 12:40
    professionalVolynsky Alex24-May-12 12:40 
    GeneralMy vote of 5 Pin
    jfriedman23-May-12 4:16
    jfriedman23-May-12 4:16 
    AnswerRe: My vote of 5 Pin
    Volynsky Alex23-May-12 4:42
    professionalVolynsky Alex23-May-12 4:42 
    QuestionMy vote of 5 Pin
    Sharjith23-May-12 3:30
    professionalSharjith23-May-12 3:30 
    You have exposed and explained a caveat in a very nice way!
    RegardsSmile | :)
    N. Sharjith

    AnswerRe: My vote of 5 Pin
    Volynsky Alex23-May-12 3:40
    professionalVolynsky Alex23-May-12 3:40 
    NewsMy vote of 5 Pin
    GlebGeglov23-May-12 0:22
    GlebGeglov23-May-12 0:22 
    GeneralRe: My vote of 5 Pin
    Volynsky Alex23-May-12 1:15
    professionalVolynsky Alex23-May-12 1:15 
    GeneralMy vote of 1 Pin
    Rolf Kristensen22-May-12 23:37
    Rolf Kristensen22-May-12 23:37 

    General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

    Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.