0

I was trying to revise my Object Oriented programming concepts. While going through this basic C++ example here, I saw that the this-> keyword has not been used when setting values for the member variables. I then modified this program to set use the this keyword. Surprisingly, both work (this and this).

#include <iostream>      // for cout and cin

class Cat                   // begin declaration of the class
{
  public:                    // begin public section
    Cat(int initialAge);     // constructor
    Cat(const Cat& copy_from); //copy constructor
    Cat& operator=(const Cat& copy_from); //copy assignment
    ~Cat();                  // destructor

    int GetAge() const;            // accessor function
    void SetAge(int age);    // accessor function
    void Meow();
 private:                   // begin private section
    int itsAge;              // member variable
    char * string;
};

 // constructor of Cat,
Cat::Cat(int initialAge)
{
  itsAge = initialAge;
  string = new char[10]();
}

//copy constructor for making a new copy of a Cat
Cat::Cat(const Cat& copy_from) {
   itsAge = copy_from.itsAge;
   string = new char[10]();
   std::copy(copy_from.string+0, copy_from.string+10, string);
}

//copy assignment for assigning a value from one Cat to another
Cat& Cat::operator=(const Cat& copy_from) {
   itsAge = copy_from.itsAge;
   std::copy(copy_from.string+0, copy_from.string+10, string);
}

Cat::~Cat()                 // destructor, just an example
{
    delete[] string;
}

// GetAge, Public accessor function
// returns value of itsAge member
int Cat::GetAge() const
{
   return itsAge;
}

// Definition of SetAge, public
// accessor function

 void Cat::SetAge(int age)
{
   // set member variable its age to
   // value passed in by parameter age
   itsAge = age;
}

// definition of Meow method
// returns: void
// parameters: None
// action: Prints "meow" to screen
void Cat::Meow()
{
   cout << "Meow.\n";
}

// create a cat, set its age, have it
// meow, tell us its age, then meow again.
int main()
{
  int Age;
  cout<<"How old is Frisky? ";
  cin>>Age;
  Cat Frisky(Age);
  Frisky.Meow();
  cout << "Frisky is a cat who is " ;
  cout << Frisky.GetAge() << " years old.\n";
  Frisky.Meow();
  Age++;
  Frisky.SetAge(Age);
  cout << "Now Frisky is " ;
  cout << Frisky.GetAge() << " years old.\n";
  return 0;
}

So my question is, should we, or shouldn't we use this keyword in this context (when setting the values of the member variables)? Thanks!

Edit: Or, is this a personal preference as mentioned here?

  • As you have discovered, it does not matter. It is mostly a stylistic issue. Sometimes, it adds clarity for the reader by making explicit that the variable is a member variable. – Brad S. Sep 14 '17 at 23:25
  • @BradS. I might be wrong here, but does Java _mandate_ it? –  Sep 14 '17 at 23:25
  • 5
    Mostly personal preference. About the only time you should need to use `this` if you like to walk on the wild side and use the same names for parameters and member variables. – user4581301 Sep 14 '17 at 23:26
  • @UmedhSinghBundela: Java doesn't mandate it either. It's only needed [when there is ambiguity](http://docs.oracle.com/javase/tutorial/java/javaOO/thiskey.html); if you take an argument named `x` and have a member named `x`, you need to say `this.x` to refer to the member (`x` would be the argument otherwise). – ShadowRanger Sep 14 '17 at 23:28
  • 1
    With regards to the constructor you may find advantages in using the [Member Initializer List](http://en.cppreference.com/w/cpp/language/initializer_list) instead of assigning members inside the body of the constructor. All members must be initialized before entering the body of the constructor, and the Member Initializer List gives you a chance to specify the initialization value before the compiler wastes time setting the member to its default. – user4581301 Sep 14 '17 at 23:32
  • Got your points. Thank you, everyone. Appreciate your help! :) –  Sep 14 '17 at 23:37
  • 3
    One reason to write `this->` is that it will prompt a list of class members to pop up in your IDE ; and then you forget to go back and delete the `this->` after you chose the one you wanted... – M.M Sep 14 '17 at 23:43
  • 2
    As `this->` is sometimes needed to disambiguate things when you "walk on the wild side", using it when *not* needed will make people like me wonder what you are up to. "What the heck is he trying to disambiguate here?! Did I miss something *really* advanced?". And so the code takes longer to read. – Bo Persson Sep 15 '17 at 00:19

2 Answers2

0

In the context of the example the keyword this is usually used for self-documentation to distinguish non-static members of the class from local variables.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • And `static` members of the class can be invoked without any object; so the ambiguity doesn't arise in the first place, correct? –  Sep 14 '17 at 23:38
  • @UmedhSinghBundela I have not understood your question. Nevertheless local variables can hide static data members. In this case static data members are prefixed with the class name as for example Cat::static_member. By the way you can use class name also for non-static data members instead of the keyword this. – Vlad from Moscow Sep 14 '17 at 23:41
  • Or for when you need the pointer to the class instance (i.e. "a pointer to the calling object.") – Saustin Sep 15 '17 at 01:27
0

Constructor:

// constructor of Cat,
Cat::Cat(int initialAge)
{
  itsAge = initialAge;
  string = new char[10]();
}

You should write this as:

// constructor of Cat,
Cat::Cat(int itsAge)
: itsAge(itsAge),
string(new char[10])
{
}

Copy constructor:

//copy constructor for making a new copy of a Cat
Cat::Cat(const Cat& copy_from) {
   itsAge = copy_from.itsAge;
   string = new char[10]();
   std::copy(copy_from.string+0, copy_from.string+10, string);
}

You should write this as:

Cat::Cat(const Cat& copy_from)
: itsAge(copy_from.itsAge),
string(new char[10])
{
   std::copy(copy_from.string, copy_from.string+sizeof string, string);
}

Copy assignment:

//copy assignment for assigning a value from one Cat to another
Cat& Cat::operator=(const Cat& copy_from) {
   itsAge = copy_from.itsAge;
   std::copy(copy_from.string+0, copy_from.string+10, string);
}

You should write this as:

Cat& Cat::operator=(const Cat& copy_from)
{
   this->itsAge = copy_from.itsAge;
   std::copy(copy_from.string, copy_from.string + sizeof string, string);
}

Mutator:

// Definition of SetAge, public
// accessor function

void Cat::SetAge(int age)
{
   // set member variable its age to
   // value passed in by parameter age
   itsAge = age;
}

You should write this as:

void Cat::SetAge(int itsAge)
{
   this->itsAge = itsAgege;
}

In other words:

  • use member initialization lists wherever possible
  • use the same name for arguments as for the members they are going into, to economize on identifiers and increase clarity
  • use this-> where necessary to eliminate ambiguity or error.
user207421
  • 305,947
  • 44
  • 307
  • 483