How to understand the C++ implicit parameter "this" [closed] - c++

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
if we create a class like this :
class Sales_data
{
std::string isbn() const {return bookNo;}
std::string bookNo;
};
And we make a object total;
Sales_data total;
total.isbn();
The C++ Primer, fifth edition, says (page 258),"when we call a member function, this is initialized with the address of the object on which the function was invoked "
,it like this:
Sales_data::isbn(&total)
and the book also write,we can get the bookNo like :
std::string isbn()const {return this->bookNo;}
I think the implicit parameter "this" just like a pointer,
but i can't see it type,would anybody help me point what wrong i think and what should i do to understand the implicit parameter 'this' and this parameter works for?
#Jason C
my extra question:
this is a pointer,so it behave like a normal pointer,
#include "iostream"
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
int a = 1;
int * b = &a;
cout << "the b is " << b << endl;
cout << "the &a is " << &a << endl;
cout << "the *b is " << *b << endl;
cout << "the &b is" << &b << endl;
return 0;
}
on my computer the output is :
the b is 0110FCEC
the &a is 0110FCEC
the *b is 1
the &b is0110FCE0
then ,What's the use of the type of the pointer.

this is not a parameter, it is a way for an object to refer to itself.
If you use visual studio or any modern IDE you can check that this has the same type as the class of which it is a member of.
There is a good book called "The C++ Object Model" by Stanley B. Lippman which can help understand.

Even if not defined as such in the standard, every implementation I am aware of makes this an implicit parameter to a member function and can be viewed as such.
In C++, you do
object->function () ;
In contrast, in Ada the syntax is
function (object) ;
The object is then an explicit parameter to the member function. The this variable is a product of C++'s member calling syntax. Instead of the programmer having to explicitly declare a parameter identifying the object (as in Ada), C++ does this automatically for you (this).
In most implementations, C++ parameters are bound to offsets to locations on the stack or to registers. This is implemented in the very same way as other parameters (either bound to a stack offset or a register).

this is a pointer to whatever instance of an object the member function is being called on (note that there is no this in static member functions or non-member functions, then).
In your case, it is either a Sales_data * or const Sales_data * depending on the context. Inside isbn(), it is the latter.
This (contrived) example illustrates its value:
class Example {
public:
void function (Example *x);
};
void Example::function (Example *x) {
if (x == this)
cout << "x is this!" << endl;
else
cout << "x is not this." << endl;
}
Now if we do:
Example a;
Example *b = new Example();
a.function(&a); // outputs "x is this!"
b->function(b); // outputs "x is this!"
a.function(b); // outputs "x is not this!"
b->function(&a); // outputs "x is not this!"
Also, since it's a pointer to the "current" instance of the object:
class Example2 {
public:
int k;
void function ();
};
void Example2::function () {
k = 42;
this->k = 42; // does the same thing as above!
}

Related

Overhead of returning reference to member variable data

I am new to C++ and get confused about what goes on under the hood when a class method returns a reference to a member variable that is raw data (rather than a pointer or a reference). Here's an example:
#include <iostream>
using namespace std;
struct Dog {
int age;
};
class Wrapper {
public:
Dog myDog;
Dog& operator*() { return myDog; }
Dog* operator->() { return &myDog; }
};
int main() {
auto w = Wrapper();
// Method 1
w.myDog.age = 1;
cout << w.myDog.age << "\n";
// Method 2
(*w).age = 2;
cout << w.myDog.age << "\n";
// Method 3
w->age = 3;
cout << w.myDog.age << "\n";
}
My question is: what happens at runtime when the code reads (*w) or w-> (as in the main function)? Does it compute the address of the myDog field every time it sees (*it) or it->? Is there overhead to either of these two access methods compared to accessing myDog_ directly?
Thanks!
Technically, what you are asking is entirely system/compiler-specific. As a practicable matter, a pointer and a reference are identical in implementation.
No rational compiler is going to treat
(*x).y
and
x->y
differently. Under the covers both usually appears in assembly language as something like
y(Rn)
Where Rn is a register holding the address of x and y is the offset of y into the structure.
The problem is that C++ is built upon C which in turn is the most f*&*) *p programming language ever devised. The reference construct is a work around to C's inept method of passing parameters.

Why is the pointer declared in main() not changed? [duplicate]

This question already has answers here:
When I change a parameter inside a function, does it change for the caller, too?
(4 answers)
Closed 4 years ago.
I know call by pointers in which we pass address of variables.Something like this:
void swap(int *x, int *y)
{
int temp;
temp = *x; /* save the value at address x */
*x = *y; /* put y into x */
*y = temp; /* put x into y */
return;
}
swap(&a, &b);
And also call by reference,in both of these methods the changes made in the function are reflected in actual arguments' variable.
But why are actual parameters passed in this case of call not changed:
#include <iostream>
using namespace std;
void foo(int* c){
c=c+1;
}
int main()
{
int a=5;
int *c=&a;
cout<<&c<<endl; //0x7ffe1a74f3b0
foo(c);
cout<<*c<<endl;//5
cout<<&c<<endl;//0x7ffe1a74f3b0
}
Here c passed to foo() is address of a.So how this is call by value.
Here c should have printed garbage value according to me.Please explain what has happened here.
And also call by reference, in both of these methods the changes made in the function are reflected in actual arguments' variable.
There is an important difference, though: the changes are always made to whatever is referenced/pointed to, never to the reference/pointer itself (modifying a reference is impossible in general).
That is why assigning c a new value inside foo has no effect on c outside foo: the pointer passed to a function is copied.
If you need to modify the pointer, you need to add another level of dereference by passing a pointer reference or a pointer to a pointer.
Following on from comments, the variable c defined in function main is a different variable to the parameter c of function foo. If you want foo to be able to modify main's c, that is modify the address that c's pointer type holds, then you need to pass either a reference or pointer to c to the function instead.
Here is an example that shows the difference between passing c by value (as int *), or by reference (as int ** or int *&). Don't be fooled by the fact that int * is a pointer type, that means that it can receive an int by reference or an int * by value. And since main's c is int * rather than int, main c is being passed by value.
Note the differences in how the functions are called (whether c needs the address operator & in the function call) and the outcome of each function.
#include <iostream>
using namespace std;
void foo_int_ptr(int* c)
{
c=c+1;
}
void foo_int_ptr_ptr(int** c)
{
*c=*c+1;
}
void foo_int_ptr_ref(int*& c)
{
c=c+1;
}
int main()
{
int a=5;
int *c=&a;
cout << "&c=" << &c << ", c=" << c << ", *c=" << (c==&a ? std::to_string(*c) : std::string("INVALID PTR")) << endl;
foo_int_ptr(c);
cout << "&c=" << &c << ", c=" << c << ", *c=" << (c==&a ? std::to_string(*c) : std::string("INVALID PTR")) << endl;
foo_int_ptr_ptr(&c);
cout << "&c=" << &c << ", c=" << c << ", *c=" << (c==&a ? std::to_string(*c) : std::string("INVALID PTR")) << endl;
foo_int_ptr_ref(c);
cout << "&c=" << &c << ", c=" << c << ", *c=" << (c==&a ? std::to_string(*c) : std::string("INVALID PTR")) << endl;
}
Output:
&c=0x7e02d81808b8, c=0x7e02d81808ac, *c=5
&c=0x7e02d81808b8, c=0x7e02d81808ac, *c=5
&c=0x7e02d81808b8, c=0x7e02d81808b0, *c=INVALID PTR
&c=0x7e02d81808b8, c=0x7e02d81808b4, *c=INVALID PTR
there is a mistake in your thinking about this ..
int *c = &a;
this doesn't mean that c "contains" address of a, this means that c is a pointer TO the address of a. Passing a pointer to foo() will not do anything.

Compiler: How is class instantiation code compiled?

Assume we have (in C++): MyClass* x = new MyClass(10)
Can someone please explain what 'exactly' happens when compiler parses this statement? (I tried taking a look at the Red Dragon book but couldn't find anything useful).
I want to know what happens in the stack/heap or compiler's symbol table. How compiler keeps track of the type of x variable? How later calls to x->method1(1,2) will be resolved to appropriate methods in MyClass (for simplicity assume there is no inheritance and MyClass is the only class that we have).
MyClass* x is a definition of pointer to object (instance) of type MyClass. Memory for that variable is allocated according to the place of its definition: if it is defined in the method, and is a local variable, stack is used. And it is memory to store the address.
Then expression new MyClass(10) is a command to allocate memory in heap for an object (instance) itself and return address to be stored in x. To fill the memory of new object MyClass (set up its initial state) special method (at least one) is executed automatically - constructor (or several in some cases) - that receives value 10 in your example.
Because C++ allows inheritance (this is also the reason for the execution of several constructors when an instance created) there are some mechanism to determine which method should be exactly called. You should read somewhere about Virtual method table.
In the simplest case (without inheritance), type of variable x (pointer to object of type MyClass) provide all necessary information about object structure. So, x->method1(1,2) or (*x).method1(1,2) provide call of member method1 to execute it with parameters 1 and 2 (stored in stack) as well as with data that form the state of object (stored in heap) and available by this pointer inside any non-static member of class. The method itself, of course, not stored in the heap.
UPDATE:
You can make example to make same experiments, like:
#include <iostream>
#include <string>
using namespace std;
class MyClass
{
private:
int innerData;
long long int lastValue;
public:
MyClass() // default constructor
{
cout << "default constructor" << endl;
innerData = 42;
lastValue = 0;
}
MyClass(int data) // constructor with parameter
{
cout << "constructor with parameter" << endl;
innerData = data;
lastValue = 0;
}
int method1(int factor, int coefficient)
{
cout << "Address in this-pinter " << this << endl;
cout << "Address of innerData " << &innerData << endl;
cout << "Address of lastValue " << &lastValue << endl;
cout << "Address of factor " << &factor << endl;
lastValue = factor * innerData + coefficient;
return lastValue;
}
};
int main(void)
{
MyClass* x = new MyClass(10);
cout << "addres of object " << x << endl;
cout << "addres of pointer " << &x << endl;
cout << "size of object " << sizeof(MyClass) << endl;
cout << "size of pointer " << sizeof(x) << endl;
x->method1(1, 2);
}
C++ is indeed a bit nasty, and this already started in C. Just look at the first 3 tokens : MyClass * x. The compiler has to look up MyClass to determine that this is not a multiplication. Since it is a type, it shouldn't look up x either, but add x to the symbol table right there (really can't be delayed). In the ideal world of simple-to-parse languages, there would be no need to keep the symbol table up to date for every token parsed.
After the definition of x, the = signals an initializing expression. That's an easy one to parse: new is unambiguously a keyword, it's not a placement new and the type being created is right there.

C++ code error in my practice code [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 7 years ago.
Improve this question
Can you please help me out with this issue?
#include <iostream>
#include <cstring>
using namespace std;
class A
{
public:
char str[4];
A()
{
str = "C++";
cout << "Constructor A" << endl;
}
void display()
{
cout << str << " is your name" << endl;
}
};
int main()
{
A a;
a.display();
return 0;
}
It gives the following errors:
**************************Error**********
StringProg.cpp:9: error: ISO C++ forbids initialization of member "str"
StringProg.cpp:9: error: making "str" static StringProg.cpp:9: error: invalid in-class initialization of static data member of non-integral type "char [4]"
StringProg.cpp: In member function "void A::display()":
StringProg.cpp:17: error: "str" was not declared in this scope
**************************
There are quite a few issues with C arrays that prevent you from doing what you want to do.
String literals have type of const char[n] (n being their length + 1 for \0 character). To use them in C Standard Library functions, they decay to const char*, which don't carry the size of the string, and in order to find it, the strings need to be traversed (every character being looked at and compared to \0)
As a consequence, array assignment operator would need to be rather nontrivial; this isn't provided by the language, and you have to use library functions like strcpy to move the literal into your usable memory. In other words, you can't assign C arrays like other values.
Arrays function in a very primitive way; they don't have operators for comparison, it's harder to pass them to functions and store in the classes properly.
And so, because of all the above...
Prefer std::string to char[]:
class A {
std::string str;
public:
// prefer constructor init list
A() : str("C++") {
// your line would work, too
std::cout << "Constructor A" << std::endl;
}
void display() const {
std::cout << str << " is your name" << std::endl;
}
};
int main()
{
A a;
a.display();
// return 0; is unnecessary
}
Some "rules of thumb" (rules of thumbs?): if you need more than one element, start with vector<>. Never use C arrays. string is one element, not an "array of characters".
Try the following
#include<iostream>
#include<cstring>
class A
{
private:
char str[4];
public:
A() : str { "C++" }
{
std::cout << "Constructor A" << std::endl;
}
void display() const
{
std::cout << str << " is your name" << std::endl;
}
};
int main()
{
A a;
a.display();
return 0;
}
The program output is
Constructor A
C++ is your name
Take into account that arrays do not have the copy assignment operator. Thus this statement in your program
str = "C++';
even if to update the typo and write
str = "C++";
is invalid.
You could use standard C function strcpy declared in header <cstring>. For example
#include <cstring>
//...
A()
{
std::strcpy( str, "C++" );
std::cout << "Constructor A" << std::endl;
}

C++ class and friend [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions must demonstrate a minimal understanding of the problem being solved. Tell us what you've tried to do, why it didn't work, and how it should work. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
This is my code:
#include <iostream>
#include <string>
using namespace std;
class C
{
private:
string str;
friend void func();
};
void func()
{
str = "Lala";
cout << str << endl;
}
int main()
{
func();
}
I don't understand why this doesn't work.
In my bigger project I want to acces private variables of a class with a function out of class.
Here I made a class C and made a function func(); to be its friend.But still I can't use it's private variables in function.
What I did wrong and is there a better way to do this?
It doesn't work because void func(); is not a member function of the class, it's just declared as a friend function to it, meaning it can access the private members.
You have no instance of the class C, so you can't possibly refer to any valid str variable.
Next time, please also quote the errors you get. In this case, there will be a compile error stating the symbol "str" has not been defined within func().
If you want to access the member str of a class instance of C, you need such an instance, as in:
void func(){
C c;
c.str = "Lala";
cout << c.str << endl;
}
func() is not a member function, and it is not receiving any parameter of type C, what object is it supposed to operate on?
func must either be a member function of C (in which case you'll invocate it over an instance of C, and friend is not necessary), either a function that receives some parameter of type C (or create a local C object), on which it can work on, even accessing its private fields.
This doesn't work since str is not defined inside func().
You should have an instance of C.
void func()
{
C foo;
foo.str = "Lala";
cout << str << endl;
}
If you need to you can pass the C instance as a parameter:
void func(C &foo)
{
foo.str = "Lala";
cout << str << endl;
}
The problem
Let's look at your code piece by piece:
#include <iostream>
#include <string>
using namespace std;
Just a short note here: It is a bad idea to use using namespace std;.
class C
{
private:
string str;
friend void func();
};
Here you define a class C. You declare that objects of this class will contain a string, which is private (i.e. may only be accessed by class members and friends), and you declare the global function void func() a friend, that is, it is allowed to access the private members (in this case str) of the class C and of any object of type C. Note that apart from that permission, func is in no way related to the class C.
void func()
{
str = "Lala";
cout << str << endl;
}
Here you try to assign to a variable str which you never declared. Remember that there's no relation of func to the class C other than that it may access the private members of
C and objects of type C. However, there's no object of type C in sight, and even if there were, there's nothing to tell the compiler from which object str is to be taken, or even that you are speaking about the str in C. I'll remember you again that func is completely independent of C, so the code is interpreted the same way as if C wouldn't have declared it a friend.
int main()
{
func();
}
OK, nothing special here, you're just calling func.
How to fix it
Now, how to fix your code? Well, there are several possibilities:
Supplying objects
Local objects
Since str is a member of objects of class C, you'll need an object of the class. So you could for example do:
void func()
{
C object;
object.str = "Lala";
std::cout << object.str << std::endl;
}
Here you create a local object in func, assign to that object's str member a value and then outputs it. To see that different objects have different members, you can e.g. write:
void func()
{
C object1, object2;
object1.str = "Lala";
object2.str = "Lele";
std::cout << object1.str << " -- " << object2.str << "\n";
}
This outputs Lala -- Lele because the first object's str member has the value "Lala" while the second object's str member has the value "Lele".
Function arguments
Another option is that you pass the object as argument, e.g.
void func(C object)
{
std::cout << object.str << " -- ";
object.str = "Lele";
std::cout << object.str << " -- ";
}
int main()
{
C main_object;
main_object.str = "Lala";
func(main_object);
std::cout << object.str << std::endl;
}
This prints Lala -- Lele -- Lala.
What happens here is that in main an object is created, whose str member is assigned the valeu "Lala". On call to func, a copy of that object is created, which you then access from func. Since it's a copy, it initially also contains the same value "Lala", whichfuncthen outputs. Then the assignment infuncchanges thestrmember *of that copy* to"Lele"and outputs that. The original object is not affected as the output inmain` shows.
So you see, there can be several objects, and it is crucial that you say the str member of which object you want to access.
Now if you do not intend to change the object in the called function, making a copy is just a waste of time, therefore you can also pass it as a reference to const:
void func(C const& object)
{
std::cout << object.str << std::endl;
}
int main()
{
C main_object;
main_object.str = "Lala";
func(main_object);
}
The argument C const& says "I want to directly access the object the caller gives me, but I promise not to change it." The "directly access" part is denoted by the &, and the "I promise not to change it" is denoted by the const. The compiler actually checks that you hold your promise and don't try to change it (that is, if in func you tried to do object.str = "Lele", the compiler would complain (there are ways to tell the compiler to shut up about that, but you shouldn't do that; just keep your promises). However note that this applies again only to that specific object; for example, the following code is completely OK:
void func(C const& object)
{
C another_object;
another_object.str = "Lele";
std::cout << object.str << " -- " << another_object.str << std::endl;
}
int main()
{
C main_object;
main_object.str = "Lala";
func(main_object);
}
This gives no error and prints Lala -- Lele because you're dealing again with different objects.
Of course there may be the case that you do want to change the object you are passed. Then you can just use & without const:
void func(C& object)
{
std::cout << object.str << " -- ";
object.str = "Lele";
std::cout << object.str << " -- ";
}
int main()
{
C main_object;
main_object.str = "Lala";
func(main_object);
std::cout << object.str << std::endl;
}
This prints Lala -- Lele -- Lele.
Now you again directly access the object passed as argument from main, but this time, you don't promise that you don't change it, and indeed you do change it. The output from main demonstrates that indeed main_object was changed.
Making the variable a static member
Now, there's the possibility that you really want there to only ever be one str in C, not a separate one for each object of that type. If you are absolutely positive that this is what you want, then you can make str a static member of the class:
class C
{
private:
static std::string str; // note the keyword "static" here
friend void func();
};
std::string C::str; // You have to have an extra definition for class static variables!
Now you can access str without having an object of C available. However note that you still need to tell the compiler inside func that you want to access the str inside C:
void func()
{
C::str = "Lala";
std::cout << C::str << std::endl;
}
You can also access the variable on object as if it were a member of that object. However be aware that this does not mean that different objects still have their own str. For example, with the changed class definition, we will gett different behaviour for the code from above:
void func()
{
C object1, object2;
object1.str = "Lala";
object2.str = "Lele";
std::cout << object1.str << " -- " << object2.str << "\n";
}
Now we will get the output Lele -- Lele because there's only one str, which does not depend on the object (the syntax object1.str in this case is misleading in that respect; actually here it means "the str defined for the type of object1, that is, C").
void func(C* object)
{
object->str = "Lala";
cout << object->str << endl;
}
Since func is not a member of the class, so you can't call it like object.func(). Thus the function won't know which object of the class you wish to change. So you have to explicitly pass the object pointer to the function. Use a reference would also do.
Or you can declare str as static. But static member will make all instances of the class share the same value.