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.
Related
# include <iostream>
# include <string>
using std::string;
using std::cout;
using std::endl;
string func() {
string abc = "some string";
return abc;
}
void func1(string s) {
cout << "I got this: " << s << endl;
}
int main() {
func1(func());
}
This gives:
$ ./a.out
I got this: some string
How/why does this code work ? I wonder because abc went out of scope and got destroyed as soon as the call to func() completed. So a copy of abc cannot be/should not be available in variable s in function func1 Is this understanding correct ?
The return value is copied from the local variable, effectively creating a new string object.
However, RVO (returned value optimization) should eliminate this step.
Try single stepping your code in a debugger. You should see the std::string copy constructor called for the return line. Be sure to compile with debug enabled and optimizers off.
Your code is essentially asking:
"Call func1, and in order for func1 to work I have to receive a string which we can use by calling the copy constructor on that string. The parameter for func1 we want to come from the return value of func (which we know has to be a string since its explicitly defined".
abc goes out of scope only after the copy constructor is called on the return value of func() which passes the value of the string. In theory you could have written it passed by reference or constant reference:
void func1(string& s) {
cout << "I got this: " << s << endl;
}
Which allows func1 to directly access the string in memory through a pointer (and also change it, if your code was meant to.)
void func1(string const& s) {
cout << "I got this: " << s << endl;
}
Which provides a constant reference to the string from func(). This ensures that you get a pointer to the data and that you won't change its contents. Typically passing data by constant reference (const&) is desirable because it's very fast and keeps your code from accidentally changing data that it shouldn't.
You really only need to pass by value if you're going to manipulate the data once you pass it to the new function, saving you the resources of creating another new container to handle the manipulation:
void func1(string s) {
s += " some extra stuff to add to the end of the string"; //append some new data
cout << "I got this: " << s << endl;
}
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.
Lets take the example some of the codes like the following use objects but can access their members directly without using any '.' operator
Eg-1
#include <iostream>
#include <string>
using namespace std;
int main () {
string mystr;
cout << "What's your name? ";
getline (cin, mystr);
cout << "Hello " << mystr << ".\n";
cout << "What is your favorite team? ";
getline (cin, mystr);
cout << "I like " << mystr << " too!\n";
return 0;
}
Here mystr is an object of std::string but it can access the group of characters inside it without using the '.' operator it should be
getline(cin,mystr.(member_name)); //Here member name is the name of the member which is there inside the class std::string and stores the data
But the actual working code is
getline(cin,mystr);
Second thing what is indirection
Edit 1:
Ok let me put this in a more simpler way if i have some class which has some data members and if i want to use any data member then i need to refer it from the object like
Eg-2
class reff{
public:
int a;
int b;
}
reff per;
per.a=36;
This statement tells that to access any class' members we need to refer it from the object but the same is not happening in the example of std:: string which i have mentioned above mystr is an object so it must be having some data member to store the data if i want to display the data inside a std::string object then i should mention the data member's name along with the objects name but in Eg-1 only object's name is mentioned.
The reason the call to getline(cin,mystr); does not directly specify any of the members of mystr is because the getline() function requires a string object, not one of its member variables. The actual implementation will access the individual members, but as a user of the string class, you don't need to (or want to) know those details. This concept is known as encapsulation, and allows you to seperate what a thing does (stores and allows access to a string of characters) from how it does it (pointers and length counters, static buffers, or whatever).
In your example:
class reff{
public:
int a;
int b;
};
reff per;
per.a=36;
you directly access the a member, but we could write a function which requires a reference to a reff object to set the value of its member variable:
void setValueA(reff& obj, int value)
{
obj.a = value;
}
and then use similar syntax to the getline() method on it:
setValueA(per, 36);
to achieve the same thing as per.a = 36, but with the benefits of encapsulation: if you later need to change the details of how reff stores its data (e.g. changing a and b to meaningful names), you only need to change the function implementation to use the new data members; all user code using this class will continue to work. If user code directly accessed the members, it would also need to be changed to use the new name.
Notice that setValueA() is accessing the member variables of the object it is passed; so calling it with per.a directly is not only unnecessary, but impossible:
setValueA(per.a, 36); // invalid: setValueA() requires a reff&, not an int
since the function itself tries to utilise the member a of the object it is passed, and an int does not have any members.
For the getline() call using a std::string, it has the same issue: for this function to work, it needs at the minimum:
read/write access to a pointer to the memory to store the data it reads (it may need to reallocate this if there's not enough space already allocated); and
the amount of memory pointed to the above, so it knows how much additional data it can store before it needs to allocate additional space.
So, given that getline() requires more than just a single intrinsic type in order to function, it should be clear why the parameter includes a string object rather than one of its specific member variable.
For additional examples, you should look up operator overloading, which can even let you do things like have per = 36; assign a value to per.a.
Here's a self-contained example using overloaded operators on a slightly modified version of your reff class. The comments try to explain what's going on, and should give you terms you can search for - this stuff is all pretty basic C++ and should be covered in any tutorial series.
#include <iostream>
class Reff
{
public:
int a;
float b; // changed the data type to illustrate overloading the = operator
// operator= will be called if we try to assign to a an object of this class;
// this version of the function accepts an integer value
Reff& operator= (int intval)
{
a = intval;
return *this;
}
// another operator=, this one accepting a float value as the parameter
Reff& operator= (float floatval)
{
b = floatval;
return *this;
}
};
// operator+ will be called if we try to add a value to this object;
// I'm only defining this one which accepts an int value
int operator+ (Reff const& reff, int intval)
{
return reff.a + intval;
}
// an overload of the operator<< function, which accepts a reference to
// an instance of a Reff, along with the output stream parameter.
std::ostream& operator<< (std::ostream& stream, Reff const& reff)
{
return stream << "[a:" << reff.a << " b:" << reff.b << "]";
}
int main()
{
// create an instance of our class
Reff per;
// assign the instance 42 (an integer value) - this will use the integer
// overload of the operator= we defined
per = 42;
// assign it a floating point value - this will use the float overload
// of the operator=. Note that if we didn't define a float-specific overload,
// the compiler would probably truncate the value to an integer and use our
// integer version instead - possibly with a warning, possibly silently,
// depending on your compiler settings.
per = 3.14159f;
// output the object; this will use the overload of the operator<< function
// that we created, which accepts our Reff object
std::cout << per << std::endl;
// output the result of adding 58 to our object; this will use the operator+
// overload which accepts an integer
std::cout << "per + 58 = " << (per + 58) << std::endl;
}
Here you can get output directly through
cout << "I like " << mystr << " too!\n";
because operator << is overridden in string Class.
like:
ostream& operator << (ostream& OS, MyString & S)
{
OS << S.get_string();
return OS;
}
Check whole implementation : http://www.cplusplus.com/forum/beginner/15396/
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!
}
Can someone tell why test(2) object is destroyed after test_method() call?
#include<iostream>
#include<string>
using namespace std;
class test
{
int n;
public:
test(int n) : n(n)
{
cout << "test: " << n << endl;
}
~test()
{
cout << "~test: " << n << endl;
}
test & test_method()
{
cout << "test_method: " << n << endl;
return *this;
}
};
int main(int argc, const char *argv[])
{
cout << "main start" << endl;
const test &test1 = test(1);
const test &test2 = test(2).test_method();
cout << "main end" << endl;
}
Output is:
main start
test: 1
test: 2
test_method: 2
~test: 2
main end
~test: 1
test(2).test_method() returns a reference, which is bound to test2, and then the object to which it refers is destroyed at the end of the full expression, since it is a temporary object. That should not be a surprise.
The real surprise is that test1 remains a valid reference, because it is directly bound to a temporary, and binding a temporary to a reference extends the lifetime of the temporary to that of the reference variable.
You only have to note that in the test(2) case, the temporary object isn't bound to anything. It's just used to invoke some member function, and then its job is done. It doesn't "babysit" member functions, or in other words, lifetime extension isn't transitive through all possible future references.
Here's a simple thought experiment why it would be impossible to actually have "arbitrary lifetime extension":
extern T & get_ref(T &);
{
T const & x = get_ref(T());
// stuff
// Is x still valid?
}
We have no idea if x remains valid beyond the first line. get_ref could be doing anything. If it's implemented as T & get_ref(T & x) { return x; }, we might hope for magic, but it could also be this:
namespace { T global; }
T & get_ref(T & unused) { return global; }
It's impossible to decide within the original translation unit whether anything needs to be extended or not. So the way the standard has it at present is that it's an entirely trivial, local decision, just made when looking at the reference declaration expression, what the lifetime of the temporary object in question should be.
Because the C++ standard requires this behavior. Give the object a name if you want it to persist. It will persist as long as the name.
Edit: You your example, test1 is the name that you gave to the first object, whereas the second object has obtained no name at all, and so it does not outlast evaluation of the expression.