Click here to Skip to main content
15,867,308 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

     
    GeneralRe: My vote of 5 Pin
    Volynsky Alex22-May-12 23:38
    professionalVolynsky Alex22-May-12 23:38 
    GeneralRe: My vote of 5 Pin
    Ajay Vijayvargiya23-May-12 1:06
    Ajay Vijayvargiya23-May-12 1:06 
    GeneralRe: My vote of 5 Pin
    Volynsky Alex23-May-12 3:03
    professionalVolynsky Alex23-May-12 3:03 
    GeneralRe: My vote of 5 Pin
    Ajay Vijayvargiya23-May-12 4:46
    Ajay Vijayvargiya23-May-12 4:46 
    GeneralRe: My vote of 5 Pin
    Volynsky Alex23-May-12 5:27
    professionalVolynsky Alex23-May-12 5:27 
    SuggestionMy vote of 5 Pin
    Y.Desros22-May-12 12:58
    Y.Desros22-May-12 12:58 
    Questionyou have cast away const... Pin
    S Nelson22-May-12 10:09
    S Nelson22-May-12 10:09 
    AnswerRe: you have cast away const... Pin
    Volynsky Alex22-May-12 11:42
    professionalVolynsky Alex22-May-12 11:42 
    I agree.
    But believe me not everyone knows it.
    Especially those new to C++
    ale44ko

    GeneralRe: you have cast away const... Pin
    Pablo Aliskevicius23-May-12 0:20
    Pablo Aliskevicius23-May-12 0:20 
    GeneralRe: you have cast away const... Pin
    Volynsky Alex23-May-12 3:33
    professionalVolynsky Alex23-May-12 3:33 
    GeneralMy vote of 5 Pin
    S.Goldenzwaig22-May-12 8:21
    S.Goldenzwaig22-May-12 8:21 
    GeneralRe: My vote of 5 Pin
    Volynsky Alex22-May-12 11:45
    professionalVolynsky Alex22-May-12 11:45 
    GeneralRe: My vote of 5 Pin
    Paul M Watt23-May-12 13:06
    mentorPaul M Watt23-May-12 13:06 
    GeneralRe: My vote of 5 Pin
    Volynsky Alex23-May-12 14:11
    professionalVolynsky Alex23-May-12 14:11 
    GeneralMy vote of 3 Pin
    Aescleal22-May-12 8:03
    Aescleal22-May-12 8:03 
    GeneralRe: My vote of 3 Pin
    Mauro Leggieri22-May-12 11:05
    Mauro Leggieri22-May-12 11:05 
    GeneralRe: My vote of 5 Pin
    Volynsky Alex24-May-12 12:42
    professionalVolynsky Alex24-May-12 12:42 
    GeneralRe: My vote of 5 Pin
    Mauro Leggieri24-May-12 14:34
    Mauro Leggieri24-May-12 14:34 
    GeneralRe: My vote of 3 Pin
    jfriedman23-May-12 4:25
    jfriedman23-May-12 4:25 
    QuestionCouple of potential issues with your article PinPopular
    SimonSays22-May-12 5:58
    SimonSays22-May-12 5:58 
    AnswerRe: About my article Pin
    Volynsky Alex22-May-12 12:06
    professionalVolynsky Alex22-May-12 12:06 
    AnswerRe: Couple of potential issues with your article Pin
    jfriedman23-May-12 4:26
    jfriedman23-May-12 4:26 

    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.