function within structures

cerebrum's Avatar
Go4Expert Member
Code: C++
#include<iostream.h>
#include<conio.h>

using namespace std;

struct emp
{
    private:
       int h;

    public:
        void setdata(int a)
        {             
            h = a;
            cout<<h;
         }       
}emp1;
       
main()
{
    emp1.setdata(5);
    getch();
}
Hello there,

I wanted to know if there is any way by which I can view the emp1 member value (without omitting private specifier) like this :

cout<<emp1.h;

thanx !

Last edited by SaswatPadhi; 12Jul2009 at 18:01..
SaswatPadhi's Avatar, Join Date: May 2009
~ Б0ЯИ Τ0 С0δЭ ~
You can simply define a public accessor function to read the value of h.
Something like :
Code: C++
void getdata()
{
    cout<<h;
}

So, your test program becomes :
Code: C++
#include<iostream.h>
#include<conio.h>

using namespace std;

struct emp
{
private:
    int h;

public:
    void setdata(int a)
    {
        h = a;
        cout<<h;
    }

    void getdata()
    {
        cout<<h;
    }
}emp1;

int main()
{
    cout << "Initialised emp1.h with : ";
    emp1.setdata(5);
    cout << endl;
    getch();
    cout << "Reading value of emp1.h : ";
    emp1.getdata();
    cout << endl;
    getch();
    return 0;
}
xpi0t0s's Avatar, Join Date: Aug 2004
Mentor
(1) Within the rules: No. Private data is private data and the whole point is that you _can't_ access it unless you're a member function or a friend.

(2) Outside the rules: Yes. Just find the pointer to the object, work out the offset of h within the object and add that offset in bytes to the pointer, cast it to an int* and dereference the pointer.

Code:
struct emp
{
private:
    int h;

public:
    void setdata(int a)
    {
        h = a;
    }
}emp1;

void hackemp()
{
	emp1.setdata(5);
	int *foo=(int*)&emp1;
	// Assume offset of h is zero as it's the first thing in the class
	printf("emp1.h=%d\n",*foo);
	// Just to prove we're not cheating
	emp1.setdata(10);
	printf("emp1.h=%d\n",*foo);
}
Output:
emp1.h=5
emp1.h=10
cerebrum's Avatar
Go4Expert Member
thanx both of u ! I have tried the code and it ran good , though the "offset" stuff was a bit new to me, I am trying to understand it. In the mean time I would appreciate if u "explain" it.
xpi0t0s's Avatar, Join Date: Aug 2004
Mentor
Well if I can say this without sounding patronising, if you don't understand that then you should stick to the rules until you understand how this is all supposed to work. Once you get that lot, then you'll have enough knowledge to understand what I did in part 2, but if you try the advanced stuff before you get the easy stuff nailed then you'll develop loads of bad habits. For your stage, the only answer is 1: you can't, and you need an accessor function.
cerebrum's Avatar
Go4Expert Member
u seem right but let me know where can i get the proper stuff to understand this. i googled but could not find anything !
xpi0t0s's Avatar, Join Date: Aug 2004
Mentor
Focus on the basics first otherwise this will confuse you.

Basically structure/class members are stored as a data structure in memory, one after the other. So if you have:
Code:
class foo
{
int x;
char y[10];
double z;
};
then at an instantiation of class foo at address 1000 then **depending on how the compiler implements this**, there could be an integer at 1000, 10 chars at 1004 and a double at 1014. So to get at z without an accessor function, assuming the definition foo bar;, you would use something like char *hack=(char*)&bar; double *z_ptr=&(hack[14]);
Tried it in Visual Studio 2008:
Code:
struct emp
{
private:
    int x;
	char y[10];
	double z;

public:
	void wibble()
	{
		printf("this=0x%08lx; &x=0x%08lx; &y=0x%08lx; &z=0x%08lx\n",this,&x,&y,&z);
	}
    void setdata(double a)
    {
        z = a;
    }
}emp1;

void hackemp()
{
	emp1.setdata(5.7);
	emp1.wibble();

	char *hack=(char*)&emp1;
	double *z_ptr=(double*)&hack[16];
	printf("hack=0x%08lx; z_ptr=0x%08lx\n",hack,z_ptr);

	printf("emp1.z=%f\n",*z_ptr);
}
wibble just prints the addresses of this, x,y and z.
The first printf just checks I've worked out z_ptr correctly.
The second printf displays the value of z without using an accessor function.

Output:
Code:
this=0x00417140; &x=0x00417140; &y=0x00417144; &z=0x00417150
hack=0x00417140; z_ptr=0x00417150
emp1.z=5.700000
***THIS IS NOT PORTABLE AND IS NOT RECOMMENDED***
Use *only* if you have no other choice.
An accessor function is much better.
cerebrum's Avatar
Go4Expert Member
sure, i just wanted to understand. regarding the use, i won't be using it until my basics get strengthened.
thanx a ton !
cerebrum's Avatar
Go4Expert Member
int *foo=(int*)&emp1;

address of emp1 is stored in pointer foo by typecasting it to int*

I want to know why we can not assign foo the address of emp1 in this way :
int *foo = &emp1;

because emp1 is an object and not an integer variable ?

also, why can not we access the data without this typecast like :

cout<<*&emp1;

Last edited by cerebrum; 13Jul2009 at 17:36..
xpi0t0s's Avatar, Join Date: Aug 2004
Mentor
The compiler will throw an error because it's illegal to assign a pointer-to-emp1 to a pointer-to-int. So the cast is needed to override the compiler's check. Were it not for that check then your suggested code would be fine.

NB: only use casts where you really know what you're doing. Using casts to solve compiler errors/warnings is not a good general solution.