When should I explicitly write this->member in a method of
a class?
Usually, you do not have to, this-> is implied.
Sometimes, there is a name ambiguity, where it can be used to disambiguate class members and local variables. However, here is a completely different case where this-> is explicitly required.
Consider the following code:
template<class T>
struct A {
T i;
};
template<class T>
struct B : A<T> {
T foo() {
return this->i; //standard accepted by all compilers
//return i; //clang and gcc will fail
//clang 13.1.6: use of undeclared identifier 'i'
//gcc 11.3.0: 'i' was not declared in this scope
//Microsoft C++ Compiler 2019 will accept it
}
};
int main() {
B<int> b;
b.foo();
}
If you omit this->, some compilers do not know how to treat i. In order to tell it that i is indeed a member of A<T>, for any T, the this-> prefix is required.
Note: it is possible to still omit this-> prefix by using:
template<class T>
struct B : A<T> {
int foo() {
return A<T>::i; // explicitly refer to a variable in the base class
//where 'i' is now known to exist
}
};
If you declare a local variable in a method with the same name as an existing member, you will have to use this->var to access the class member instead of the local variable.
#include <iostream>
using namespace std;
class A
{
public:
int a;
void f() {
a = 4;
int a = 5;
cout << a << endl;
cout << this->a << endl;
}
};
int main()
{
A a;
a.f();
}
prints:
5
4
There are several reasons why you might need to use this pointer explicitly.
When you want to pass a reference to your object to some function.
When there is a locally declared object with the same name as the member object.
When you're trying to access members of dependent base classes.
Some people prefer the notation to visually disambiguate member accesses in their code.
Although I usually don't particular like it, I've seen others use this-> simply to get help from intellisense!
There are few cases where using this must be used, and there are others where using the this pointer is one way to solve a problem.
1) Alternatives Available: To resolve ambiguity between local variables and class members, as illustrated by #ASk.
2) No Alternative: To return a pointer or reference to this from a member function. This is frequently done (and should be done) when overloading operator+, operator-, operator=, etc:
class Foo
{
Foo& operator=(const Foo& rhs)
{
return * this;
}
};
Doing this permits an idiom known as "method chaining", where you perform several operations on an object in one line of code. Such as:
Student st;
st.SetAge (21).SetGender (male).SetClass ("C++ 101");
Some consider this consise, others consider it an abomination. Count me in the latter group.
3) No Alternative: To resolve names in dependant types. This comes up when using templates, as in this example:
#include <iostream>
template <typename Val>
class ValHolder
{
private:
Val mVal;
public:
ValHolder (const Val& val)
:
mVal (val)
{
}
Val& GetVal() { return mVal; }
};
template <typename Val>
class ValProcessor
:
public ValHolder <Val>
{
public:
ValProcessor (const Val& val)
:
ValHolder <Val> (val)
{
}
Val ComputeValue()
{
// int ret = 2 * GetVal(); // ERROR: No member 'GetVal'
int ret = 4 * this->GetVal(); // OK -- this tells compiler to examine dependant type (ValHolder)
return ret;
}
};
int main()
{
ValProcessor <int> proc (42);
const int val = proc.ComputeValue();
std::cout << val << "\n";
}
4) Alternatives Available: As a part of coding style, to document which variables are member variables as opposed to local variables. I prefer a different naming scheme where member varibales can never have the same name as locals. Currently I'm using mName for members and name for locals.
Where a member variable would be hidden by
a local variable
If you just want
to make it explictly clear that you
are calling an instance method/variable
Some coding standards use approach (2) as they claim it makes the code easier to read.
Example:
Assume MyClass has a member variable called 'count'
void MyClass::DoSomeStuff(void)
{
int count = 0;
.....
count++;
this->count = count;
}
One other case is when invoking operators. E.g. instead of
bool Type::operator!=(const Type& rhs)
{
return !operator==(rhs);
}
you can say
bool Type::operator!=(const Type& rhs)
{
return !(*this == rhs);
}
Which might be more readable. Another example is the copy-and-swap:
Type& Type::operator=(const Type& rhs)
{
Type temp(rhs);
temp.swap(*this);
}
I don't know why it's not written swap(temp) but this seems to be common.
The other uses for this (as I thought when I read the summary and half the question... .), disregarding (bad) naming disambiguation in other answers, are if you want to cast the current object, bind it in a function object or use it with a pointer-to-member.
Casts
void Foo::bar() {
misc_nonconst_stuff();
const Foo* const_this = this;
const_this->bar(); // calls const version
dynamic_cast<Bar*>(this)->bar(); // calls specific virtual function in case of multi-inheritance
}
void Foo::bar() const {}
Binding
void Foo::baz() {
for_each(m_stuff.begin(), m_stuff.end(), bind(&Foo:framboozle, this, _1));
for_each(m_stuff.begin(), m_stuff.end(), [this](StuffUnit& s) { framboozle(s); });
}
void Foo::framboozle(StuffUnit& su) {}
std::vector<StuffUnit> m_stuff;
ptr-to-member
void Foo::boz() {
bez(&Foo::bar);
bez(&Foo::baz);
}
void Foo::bez(void (Foo::*func_ptr)()) {
for (int i=0; i<3; ++i) {
(this->*func_ptr)();
}
}
Hope it helps to show other uses of this than just this->member.
You only have to use this-> if you have a symbol with the same name in two potential namespaces. Take for example:
class A {
public:
void setMyVar(int);
void doStuff();
private:
int myVar;
}
void A::setMyVar(int myVar)
{
this->myVar = myVar; // <- Interesting point in the code
}
void A::doStuff()
{
int myVar = ::calculateSomething();
this->myVar = myVar; // <- Interesting point in the code
}
At the interesting points in the code, referring to myVar will refer to the local (parameter or variable) myVar. In order to access the class member also called myVar, you need to explicitly use "this->".
You need to use this to disambiguate between a parameters/local variables and member variables.
class Foo
{
protected:
int myX;
public:
Foo(int myX)
{
this->myX = myX;
}
};
The main (or I can say, the only) purpose of this pointer is that it points to the object used to invoke a member function.
Base on this purpose, we can have some cases that only using this pointer can solve the problem.
For example, we have to return the invoking object in a member function with argument is an same class object:
class human {
...
human & human::compare(human & h){
if (condition)
return h; // argument object
else
return *this; // invoking object
}
};
I found another interesting case of explicit usage of the "this" pointer in the Effective C++ book.
For example, say you have a const function like
unsigned String::length() const
You don't want to calculate String's length for each call, hence you want to cache it doing something like
unsigned String::length() const
{
if(!lengthInitialized)
{
length = strlen(data);
lengthInitialized = 1;
}
}
But this won't compile - you are changing the object in a const function.
The trick to solve this requires casting this to a non-const this:
String* const nonConstThis = (String* const) this;
Then, you'll be able to do in above
nonConstThis->lengthInitialized = 1;
Related
Is there a nice way to have a non static value as default argument in a function? I've seen some older responses to the same question which always end up in explicitly writing out the overload. Is this still necessary in C++17?
What I'd like to do is do something akin to
class C {
const int N; //Initialized in constructor
void foo(int x = this->N){
//do something
}
}
instead of having to write
class C {
const int N; //Initialized in constructor
void foo(){
foo(N);
}
void foo(int x){
//do something
}
}
which makes the purpose of the overload less obvious.
One relatively elegant way (in my opinion) would be to use std::optional to accept the argument, and if no argument was provided, use the default from the object:
class C {
const int N_; // Initialized in constructor
public:
C(int x) :N_(x) {}
void foo(std::optional<int> x = std::nullopt) {
std::cout << x.value_or(N_) << std::endl;
}
};
int main() {
C c(7);
c.foo();
c.foo(0);
}
You can find the full explanation of what works/doesn't work in section 11.3.6 of the standard. Subsection 9 describes member access (excerpt):
A non-static member shall not appear in a default argument unless it
appears as the id-expressionof a class member access expression
(8.5.1.5) or unless it is used to form a pointer to member
(8.5.2.1).[Example:The declaration of X::mem1()in the following example
is ill-formed because no object is supplied for the non-static
memberX::a used as an initializer.
int b;
class X {
int a;
int mem1(int i = a);// error: non-static memberaused as default argument
int mem2(int i = b);// OK; useX::b
static int b;
};
Hi I want to call an objects function in other function but i can't. Why ?
class class1
{
private:
int var;
public:
class1(int x);
void functionO();
};
class1::class1(int x)
{
var = x;
}
void class1::functionO()
{
cout<<"text";
}
void Callfunction()
{
object1->function0();
}
int main()
{
class1 *object1;
object1 = new class1(x);
Callfunction();
}
Compilator says that
'object1' : undeclared identifier
It seems logical but how can i call that objects function within a function ?
In this code:
void Callfunction()
{
object1->function0();
}
object1 is out-of-scope. That is, the compiler doesn't know about anything named object1 from within the scope of CallFunction().
Note that even if you had defined CallFunction after main(), this would still be true. All variables are local to the scope in which they are declared.
One option is to make object1 a global, and I'm sure that you will be advised to do this. But please don't. Global variables introduce state to your program, and along with it a host of other nasty problems that are hard to fix without tearing your program apart. Don't get in to the habit of using global variables to fix all manner of scoping issues. You will regret it.
Rather, why not just pass a class1 pointer to CallFunction()? Better yet, pass a reference.
void CallFunction(class1& obj1)
{
obj1.function0();
}
int main()
{
class1 *object1;
object1 = new class1(x);
Callfunction(*object1);
}
Your problem has nothing to do with the declaration order (before or after doesn't matter). Your object1 is a local variable of main. This means that it isn't visible outside of main, unless you explicitely pass it to the function needing it or store a pointer to it in a global variable (but please don't). To solve your problem you should therefore pass your object to Callfunction:
void Callfunction(class1& object1)
{
object1.function0();
}
int main()
{
class1 object1(x);//<-- This asumes that you have actually defined x
//somewhere, otherwise replace it with an actual value
Callfunction(object1);
}
Note that I took the liberty of clearing up the unneeded indirection (and the memory leak) by constructing the object on the stack instead of on the heap.
Pass your object as (reference) parameter to your function:
class class1
{
private:
int var;
public:
class1(int x);
void function0();
};
class1::class1(int x)
: var(x) // Note: Use member initializer lists
{}
void class1::function0()
{
std::cout << "text, var = " << var << std::endl;
}
void Callfunction(class1& object)
{
object.function0();
}
int main()
{
class1 object1(10);
class1 object2(42);
Callfunction(object1);
Callfunction(object2);
}
Expected output:
text, var = 10
text, var = 42
NOTE
The declaration order also matters, you might need to use a forward declaration when class1 is declared after the compiler sees Callfunction().
The question: How can I make it so that a const reference is returned publicly and a non const reference returned privately?
I'm trying to create a read-only template for some variables in my classes. This involves a template class which returns a const reference to the data when public. However in the class I need to operate on the data so I am trying to return a reference that is not const privately. Here's the basics:
private: operator T&() { return data; }
public: operator const T&() const { return data; }
When I add the non const reference as shown above, if I try to access the variable publicly my Visual Studio 2010 cl.exe compiler tells me it cannot access the private member in the class. Something as simple as cout << myobj.x << endl if x was declared using the template will fail.
error C2248: 'proxy<T,C>::operator int &' : cannot access private member declared in class 'proxy<T,C>'
Here is the other thread for reference:
C++ - How to make read only class member variables in Visual Studio 2010 - Stack Overflow
Edit:
You asked for the code so here it is.
template <class T, class C>
class proxy {
friend C;
private:
T data;
T operator=(const T& arg) { data = arg; return data; }
operator T&() { return data; } // I'd expect this is only returned privately
public:
operator const T&() const { return data; }
};
class myClass {
public:
proxy<int,myClass> x;
void f(int i) {
x = i;
}
};
int main(int argc, char **argv)
{
myClass test;
test.f(12);
cout << test.x << endl; // Compiler error trying to access non-const T&
return 0;
}
Actually, visibility and accesibility are independent things in C++:
Visibility rules say that all the member functions are considered when resolving an overload.
Accesibility means that if the chosen overload function is not accesible from the used context (private member from outside of the class, for example) a compiler error will happen.
Some people think that private members will not participate in overload resolution if the function in called from outside of the class, but that's not the case. All functions, irrespective of the access, are considered.
About your specific problem, you do:
std::cout << test.x;
Here test is non-const, so is test.x, and of the two overload conversion functions, the non-const one is chosen. But, alas, this function is private, thus compiler error.
The quick solution is to do a const_cast:
std::cout << const_cast<const myClass&>(test).x;
Or if you prefer:
const myClass &ctest = test;
std::cout << ctest.x;
The right solution would be to just remove the non-const private one. You don't need it, since from the class context you can use the data member directly.
Frankly, it looks like you are trying to implement properties in C++ using the syntax from other languages. Properties are fine, but that's not the C++ way.
My advice is: do not fight the language, accept the syntax as it is, and just do the parenthesis thing. Or if x does not hold an invariant, just do it public.
The shortest way would be something like:
class myClass {
private:
int _x;
public:
int x() const {
return _x;
}
//if needed
void x(int value) {
_x = value;
}
};
The people that will read your code in the future (mind you, it might be me!) will greatly appreciate that you do not try and reinvent the language.
In C++, access checks are done after overload resolution. This has both advantages and disadvantages over the other possibility -- removing inaccessible functions from the candidate set.
Usually the solution is to use a different name for the private function. But it appears that you're trying to conform to a particular interface required by some functions you've befriended. I don't think there's an easy workaround for that. Private inheritance won't help in the general case, because inherited functions aren't part of the candidate set, they're hidden by a function in the derived class. But conversion functions are inherited... and after testing, it seems that the original problem recurs (even a private conversion in a private base class is found).
So I finally suggest using a named function instead of a conversion, as in:
template <typename T, typename C>
class proxy
{
friend C;
private:
T data;
T operator=(const T& arg) { data = arg; return data; }
T& mutate() { return data; }
public:
operator const T&() const { return data; }
};
class myClass
{
public:
proxy<int,myClass> x;
void f(int i)
{
x.mutate() = i;
}
};
test is not const, test.x is not const, so myClass::operator int() is a better match that myClass::operator int() const.
Access control (private/public) doesn't enter into it.
Lets say that I have a
class Dictionary
{
vector<string> words;
void addWord(string word)//adds to words
{
/...
}
bool contains(string word)//only reads from words
{
//...
}
}
Is there a way to make compiler check that contains isnt changing words vector. Ofc this is just an example with one class data member, I would like it to work with any number of data members.
P.S. I know i have no public: and private:, I left it out intentionally to make code shorter and problem clearer.
If you want the compiler to enforce this, then declare the member function const:
bool contains(string word) const
{
...
}
A const function is not allowed to modify its member variables, and can only call other const member functions (either its own, or those of its member variables).
The exception to this rule is if the member variable is declared as mutable. [But mutable should not be used as a general-purpose const workaround; it's only really meant for when situations where the "observable" state of an object should be const, but internal implementation (such as reference-counting or lazy evaluation) still needs to change.]
Note also that const does not propagate through e.g. pointers.
So in summary:
class Thingy
{
public:
void apple() const;
void banana();
};
class Blah
{
private:
Thingy t;
int *p;
mutable int a;
public:
Blah() { p = new int; *p = 5; }
~Blah() { delete p; }
void bar() const {}
void baz() {}
void foo() const
{
p = new int; // INVALID: p is const in this context
*p = 10; // VALID: *p isn't const
baz(); // INVALID: baz() is not declared const
bar(); // VALID: bar() is declared const
t.banana(); // INVALID: Thingy::banana() is not declared const
t.apple(); // VALID: Thingy::apple() is declared const
a = 42; // VALID: a is declared mutable
}
};
Mark them as const:
bool contains(string word) const
// ^^^^^^
Another positive thing: You can only call other const member functions! :)
Yet another good thing: You're allowed to call those functions on const objects of your class, example:
void foo(const Dictionary& dict){
// 'dict' is constant, can't be changed, can only call 'const' member functions
if(dict.contains("hi")){
// ...
}
// this will make the compiler error out:
dict.addWord("oops");
}
Usually declaring the method as "const" achieves this:
bool contains(string word) const
// ...
The compiler will tell you if you use any method on the class members that is not also const. Note also that you could pass the string by reference to avoid copying (making the word parameter std::string const&).
declare your function as const:
void addWord(string word) const
{
/...
}
If you try to change any members inside the body, the compiler will give an error.
Also note that inside a method declared const, you can't call other methods that are not declared const.
Make the member function const:
bool contains(string word) const
{
//...
}
When should I explicitly write this->member in a method of
a class?
Usually, you do not have to, this-> is implied.
Sometimes, there is a name ambiguity, where it can be used to disambiguate class members and local variables. However, here is a completely different case where this-> is explicitly required.
Consider the following code:
template<class T>
struct A {
T i;
};
template<class T>
struct B : A<T> {
T foo() {
return this->i; //standard accepted by all compilers
//return i; //clang and gcc will fail
//clang 13.1.6: use of undeclared identifier 'i'
//gcc 11.3.0: 'i' was not declared in this scope
//Microsoft C++ Compiler 2019 will accept it
}
};
int main() {
B<int> b;
b.foo();
}
If you omit this->, some compilers do not know how to treat i. In order to tell it that i is indeed a member of A<T>, for any T, the this-> prefix is required.
Note: it is possible to still omit this-> prefix by using:
template<class T>
struct B : A<T> {
int foo() {
return A<T>::i; // explicitly refer to a variable in the base class
//where 'i' is now known to exist
}
};
If you declare a local variable in a method with the same name as an existing member, you will have to use this->var to access the class member instead of the local variable.
#include <iostream>
using namespace std;
class A
{
public:
int a;
void f() {
a = 4;
int a = 5;
cout << a << endl;
cout << this->a << endl;
}
};
int main()
{
A a;
a.f();
}
prints:
5
4
There are several reasons why you might need to use this pointer explicitly.
When you want to pass a reference to your object to some function.
When there is a locally declared object with the same name as the member object.
When you're trying to access members of dependent base classes.
Some people prefer the notation to visually disambiguate member accesses in their code.
Although I usually don't particular like it, I've seen others use this-> simply to get help from intellisense!
There are few cases where using this must be used, and there are others where using the this pointer is one way to solve a problem.
1) Alternatives Available: To resolve ambiguity between local variables and class members, as illustrated by #ASk.
2) No Alternative: To return a pointer or reference to this from a member function. This is frequently done (and should be done) when overloading operator+, operator-, operator=, etc:
class Foo
{
Foo& operator=(const Foo& rhs)
{
return * this;
}
};
Doing this permits an idiom known as "method chaining", where you perform several operations on an object in one line of code. Such as:
Student st;
st.SetAge (21).SetGender (male).SetClass ("C++ 101");
Some consider this consise, others consider it an abomination. Count me in the latter group.
3) No Alternative: To resolve names in dependant types. This comes up when using templates, as in this example:
#include <iostream>
template <typename Val>
class ValHolder
{
private:
Val mVal;
public:
ValHolder (const Val& val)
:
mVal (val)
{
}
Val& GetVal() { return mVal; }
};
template <typename Val>
class ValProcessor
:
public ValHolder <Val>
{
public:
ValProcessor (const Val& val)
:
ValHolder <Val> (val)
{
}
Val ComputeValue()
{
// int ret = 2 * GetVal(); // ERROR: No member 'GetVal'
int ret = 4 * this->GetVal(); // OK -- this tells compiler to examine dependant type (ValHolder)
return ret;
}
};
int main()
{
ValProcessor <int> proc (42);
const int val = proc.ComputeValue();
std::cout << val << "\n";
}
4) Alternatives Available: As a part of coding style, to document which variables are member variables as opposed to local variables. I prefer a different naming scheme where member varibales can never have the same name as locals. Currently I'm using mName for members and name for locals.
Where a member variable would be hidden by
a local variable
If you just want
to make it explictly clear that you
are calling an instance method/variable
Some coding standards use approach (2) as they claim it makes the code easier to read.
Example:
Assume MyClass has a member variable called 'count'
void MyClass::DoSomeStuff(void)
{
int count = 0;
.....
count++;
this->count = count;
}
One other case is when invoking operators. E.g. instead of
bool Type::operator!=(const Type& rhs)
{
return !operator==(rhs);
}
you can say
bool Type::operator!=(const Type& rhs)
{
return !(*this == rhs);
}
Which might be more readable. Another example is the copy-and-swap:
Type& Type::operator=(const Type& rhs)
{
Type temp(rhs);
temp.swap(*this);
}
I don't know why it's not written swap(temp) but this seems to be common.
The other uses for this (as I thought when I read the summary and half the question... .), disregarding (bad) naming disambiguation in other answers, are if you want to cast the current object, bind it in a function object or use it with a pointer-to-member.
Casts
void Foo::bar() {
misc_nonconst_stuff();
const Foo* const_this = this;
const_this->bar(); // calls const version
dynamic_cast<Bar*>(this)->bar(); // calls specific virtual function in case of multi-inheritance
}
void Foo::bar() const {}
Binding
void Foo::baz() {
for_each(m_stuff.begin(), m_stuff.end(), bind(&Foo:framboozle, this, _1));
for_each(m_stuff.begin(), m_stuff.end(), [this](StuffUnit& s) { framboozle(s); });
}
void Foo::framboozle(StuffUnit& su) {}
std::vector<StuffUnit> m_stuff;
ptr-to-member
void Foo::boz() {
bez(&Foo::bar);
bez(&Foo::baz);
}
void Foo::bez(void (Foo::*func_ptr)()) {
for (int i=0; i<3; ++i) {
(this->*func_ptr)();
}
}
Hope it helps to show other uses of this than just this->member.
You only have to use this-> if you have a symbol with the same name in two potential namespaces. Take for example:
class A {
public:
void setMyVar(int);
void doStuff();
private:
int myVar;
}
void A::setMyVar(int myVar)
{
this->myVar = myVar; // <- Interesting point in the code
}
void A::doStuff()
{
int myVar = ::calculateSomething();
this->myVar = myVar; // <- Interesting point in the code
}
At the interesting points in the code, referring to myVar will refer to the local (parameter or variable) myVar. In order to access the class member also called myVar, you need to explicitly use "this->".
You need to use this to disambiguate between a parameters/local variables and member variables.
class Foo
{
protected:
int myX;
public:
Foo(int myX)
{
this->myX = myX;
}
};
The main (or I can say, the only) purpose of this pointer is that it points to the object used to invoke a member function.
Base on this purpose, we can have some cases that only using this pointer can solve the problem.
For example, we have to return the invoking object in a member function with argument is an same class object:
class human {
...
human & human::compare(human & h){
if (condition)
return h; // argument object
else
return *this; // invoking object
}
};
I found another interesting case of explicit usage of the "this" pointer in the Effective C++ book.
For example, say you have a const function like
unsigned String::length() const
You don't want to calculate String's length for each call, hence you want to cache it doing something like
unsigned String::length() const
{
if(!lengthInitialized)
{
length = strlen(data);
lengthInitialized = 1;
}
}
But this won't compile - you are changing the object in a const function.
The trick to solve this requires casting this to a non-const this:
String* const nonConstThis = (String* const) this;
Then, you'll be able to do in above
nonConstThis->lengthInitialized = 1;