the type of this* in C++

2k views Asked by At

it might sound stupid.in C++prime 5th edition P258,it says:

by default, the type of this is a const pointer to the nonconst version of the class type.for example,by default, the type of this in a Sales_data member function is Sales_data *const.

i can understand that for this* is a const pointer which means the object it points once initialized cannot change.but then it says:

although this is implicit, it follows the normal initialization rules,which means that(by default)we cannot bind this to a const object.

but i wrote the following codes,it was still compiled fine:

class Test{
public:
    Test() = default;
    Test(const string &s): teststr(" ") {};
    Test(int a) : testint(a) {};
    Test(const string &s, int a): teststr(s), testint(a) {};
    string getstr() const { return teststr; };
    int getint() { return testint; };   //there is no const here
private:
    string teststr;
    int testint = 0;
};

int main(){
    Test a("abc",2);

    cout << a.getint() << " ";
    cout << a.getstr() << endl;
    cout << endl;

    return 0;
}

so my question is : if the compiler can compile it fine whether there is a 'const' or not,why does it matter? and then the book says:

after all,the body of isbn doesn't change the object to which this points, so our function would be more flexible if this were a pointer to const.

and i'm wondering what is the flexiblity is?would you show me some examples?

5

There are 5 answers

0
Columbo On BEST ANSWER

For beginners, this is often depicted as a constant pointer.

However, this is actually a prvalue (pure rvalue) of pointer type. You can't assign anything to prvalues of fundamental type, which implies the "const-ness" of this.

The exact type of this depends on the cv-qualification of the method. A rule of thumb is that the cv-qualification is simply prepended to the usual pointer type - i.e., if a method of Class is marked const, then the type is const Class*.

if the compiler can compile it fine whether there is a 'const' or not,why does it matter?

If (and only if) the pointee type of this is const, you can't modify the members of the class.

Class const* ptr; // ptr->data is also const, not modifiable through this pointer

Class* ptr; // ptr->data isn't const - can be modified.

The const-qualifier on methods allows you to distinguish between methods for const objects and methods for non-const ones, which is often a necessity.

2
πάντα ῥεῖ On

"i can understand that for this* is a const pointer which means the object it points once initialized cannot change.but then it says:"

No, you got this wrong. Being this a const pointer means, you cannot change the pointer value itself like

 class MyClass {
      void foo() {
          MyClass a;
          this = &a; // <<< Compiler error
      }
 }

The type of this actually appears as

 MyClass * const this;

and for const instances or references

 MyClass const * const this;

Note this is different from

 const MyClass* some_const_instance_pointer;
0
Mike Seymour On

The "flexibility" is that you can call a const function on any object, constant or not. You can't call a non-const function on a const object (or reference/pointer to const).

So the following would fail:

const Test c;
cout << a.getint() << " ";   // ERROR: non-const function
cout << a.getstr() << endl;  // OK: const function

As well as this flexibility, declaring a member function const is a good idea since that will prevent you from accidentally modifying the object in a function that's not supposed to.

0
Zan Lynx On

Two questions two answers.

The this pointer cannot be reassigned. That's what is meant by const in this case. You can change the contents of the object that this points to but you cannot change which object it points to.

The extra flexibility of making a method const is that it can be used on both const and non-const objects. A non-const method cannot be used on a const object.

Example:

class A {
    int a;
    public:
    int method() const {
        return a;
    }
};

void f() {
    A a;
    const A ca;

    a.method();
    ca.method();
}
3
Vlad from Moscow On

According to the C++ Standard (9.3.2 The this pointer)

1 In the body of a non-static (9.3) member function, the keyword this is a prvalue expression whose value is the address of the object for which the function is called. The type of this in a member function of a class X is X*. If the member function is declared const, the type of this is const X*, if the member function is declared volatile, the type of this is volatile X*, and if the member function is declared const volatile, the type of this is const volatile X*.

As you see there is nothing said that this has type ClassTYpe * const of ClassType const * const. It is a prvalue that may not be modified as any prvalue except that for a prvalue of a class type you may call non-const member functions..

As for you then you mix two types a constant pointer and a pointer that points to a constant data. For example this declaration

const ClassType *p;

does not declare a constant pointer. So the pointer itself may be not initialized. On the other hand thsi declaration

ClassTYpe * const p = new ClassTYpe;

declares a constant pointer and the pointer itself shall be initialized as any other constant.

As for this quote from your book

after all,the body of isbn doesn't change the object to which this points, so our function would be more flexible if this were a pointer to const

Then it means that it would be better to define the function with qualifier const. In this case it could be called for constant and non-constant objects. Otherwise it may be called only for-non constant objects because within the function the pointer type of this is not const ClassTYpe *.