1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

function within structures

Discussion in 'C++' started by cerebrum, Jul 12, 2009.

  1. cerebrum

    cerebrum New Member

    Joined:
    Dec 15, 2008
    Messages:
    36
    Likes Received:
    1
    Trophy Points:
    0
    Code:
    #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 a moderator: Jul 12, 2009
  2. SaswatPadhi

    SaswatPadhi ~ Б0ЯИ Τ0 С0δЭ ~

    Joined:
    May 5, 2009
    Messages:
    1,343
    Likes Received:
    55
    Trophy Points:
    0
    Occupation:
    STUDENT !
    Location:
    Orissa, INDIA
    Home Page:
    You can simply define a public accessor function to read the value of h.
    Something like :
    Code:
    void getdata()
    {
        cout<<h;
    }
    So, your test program becomes :
    Code:
    #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;
    }
     
  3. xpi0t0s

    xpi0t0s Mentor

    Joined:
    Aug 6, 2004
    Messages:
    3,012
    Likes Received:
    203
    Trophy Points:
    0
    Occupation:
    Senior Support Engineer
    Location:
    England
    (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
     
  4. cerebrum

    cerebrum New Member

    Joined:
    Dec 15, 2008
    Messages:
    36
    Likes Received:
    1
    Trophy Points:
    0
    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.
     
  5. xpi0t0s

    xpi0t0s Mentor

    Joined:
    Aug 6, 2004
    Messages:
    3,012
    Likes Received:
    203
    Trophy Points:
    0
    Occupation:
    Senior Support Engineer
    Location:
    England
    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.
     
  6. cerebrum

    cerebrum New Member

    Joined:
    Dec 15, 2008
    Messages:
    36
    Likes Received:
    1
    Trophy Points:
    0
    u seem right but let me know where can i get the proper stuff to understand this. i googled but could not find anything !
     
  7. xpi0t0s

    xpi0t0s Mentor

    Joined:
    Aug 6, 2004
    Messages:
    3,012
    Likes Received:
    203
    Trophy Points:
    0
    Occupation:
    Senior Support Engineer
    Location:
    England
    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.
     
  8. cerebrum

    cerebrum New Member

    Joined:
    Dec 15, 2008
    Messages:
    36
    Likes Received:
    1
    Trophy Points:
    0
    sure, i just wanted to understand. regarding the use, i won't be using it until my basics get strengthened.
    thanx a ton !
     
  9. cerebrum

    cerebrum New Member

    Joined:
    Dec 15, 2008
    Messages:
    36
    Likes Received:
    1
    Trophy Points:
    0
    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: Jul 13, 2009
  10. xpi0t0s

    xpi0t0s Mentor

    Joined:
    Aug 6, 2004
    Messages:
    3,012
    Likes Received:
    203
    Trophy Points:
    0
    Occupation:
    Senior Support Engineer
    Location:
    England
    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.
     
  11. cerebrum

    cerebrum New Member

    Joined:
    Dec 15, 2008
    Messages:
    36
    Likes Received:
    1
    Trophy Points:
    0
    also, why can not we access the data without this typecast , dereferencing the address of emp1:

    cout<<*&emp1;
     
  12. xpi0t0s

    xpi0t0s Mentor

    Joined:
    Aug 6, 2004
    Messages:
    3,012
    Likes Received:
    203
    Trophy Points:
    0
    Occupation:
    Senior Support Engineer
    Location:
    England
    Because that will output an emp1, i.e. the whole object, not the int we're interested in.
     

Share This Page