Thread: Cant read class variable.

  1. #1
    Registered User xconspirisist's Avatar
    Join Date
    Nov 2003
    Posts
    44

    Cant read class variable.

    class.cpp

    Code:
    // testing.cpp : Defines the entry point for the console application.
    //
    
    #include "stdafx.h"
    #include "class.h"
    
    int main(int argc, char* argv[])
    {
    	char buffer[50];
    	myclass_t myclass_h;
    
    	myclass_h.set( );
    
    	sprintf( buffer, "%i", myclass_h.read_value() );
    	printf ( buffer );
    
    	myclass_h.unset( );
    
    	sprintf( buffer, "%i", myclass_h.read_value() );
    	printf ( buffer );
    
    	return 0;
    }
    
    int myclass_t::read_value ( void ) {
    	int value;
    
    	value = myclass_t::value;
    	return value;
    }
    
    void myclass_t::set ( void ) {
    	myclass_t myclass_h;
    	myclass_h.value = 1;
    }
    
    void myclass_t::unset ( void ) {
    	myclass_t myclass_h;
    	myclass_h.value = 0;
    }
    class.h

    Code:
    class myclass_t { 
    	public:
    		void set ( void );
    		void unset ( void );
    		int read_value ( void );
    	private:
    		int value;
    };
    It should return 1 and 0. Keeps returning -858993460

    Any help is much appreciated.

  2. #2
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,817
    Stuff in red is not necessary/wrong, stuff in blue is suggested replacement. I kept the printf's even though you should prefer to be using cout.

    Code:
    // testing.cpp : Defines the entry point for the console application.
    //
    
    #include "stdafx.h"
    #include "class.h"
    
    int main(int argc, char* argv[])
    {
        //char buffer[50];
        myclass_t myclass_h;
    
        myclass_h.set( );
    
        printf("%d",myclass_h.read_value());
        //sprintf( buffer, "%i", myclass_h.read_value() );
        //printf ( buffer );
    
        myclass_h.unset( );
    
        printf("%d",myclass_h.read_value());
        //sprintf( buffer, "%i", myclass_h.read_value() );
        //printf ( buffer );
    
        return 0;
    }
    
    int myclass_t::read_value ( void )
    {
        return value;
        //int value;
        //value = myclass_t::value;
        //return value;
    }
    
    void myclass_t::set ( void )
    {
        value = 1;
        //myclass_t myclass_h;
        //myclass_h.value = 1;
    }
    
    void myclass_t::unset ( void )
    {
        value = 0;
        //myclass_t myclass_h;
        //myclass_h.value = 0;
    }
    class.h
    Code:
    class myclass_t
    { 
    public:
        void set ( void );
        void unset ( void );
        int read_value ( void );
    private:
        int value;
    };
    "Owners of dogs will have noticed that, if you provide them with food and water and shelter and affection, they will think you are god. Whereas owners of cats are compelled to realize that, if you provide them with food and water and shelter and affection, they draw the conclusion that they are gods."
    -Christopher Hitchens

  3. #3
    Registered User xconspirisist's Avatar
    Join Date
    Nov 2003
    Posts
    44
    Thanks, that appears to work. However, I cant get the correct value returned without first calling set. This means, from each function that I want to access 'value', I must first set it, in each subsequent function. How can I ammend this?

    Code:
    // testing.cpp : Defines the entry point for the console application.
    //
    
    #include "stdafx.h"
    #include "class.h"
    
    void test_func ( void ) { 
    	myclass_t myclass_h;
    
    	printf ( "value from func: %d \n", myclass_h.read_value() );
    }
    
    int main(int argc, char* argv[])
    {
    	myclass_t myclass_h;
    
    	myclass_h.set ();
    
    	printf ( "value: %d \n", myclass_h.read_value() );
    
    	myclass_h.unset ();
    
    	printf ( "value: %d \n", myclass_h.read_value() );
    
    	test_func() ;
    
    	return 0;
    }
    
    bool myclass_t::read_value ( void ) {
    	return value;
    }
    
    void myclass_t::set ( void ) {
    	value = true;
    }
    
    void myclass_t::unset ( void ) {
    	value = false;
    }
    If you see, in test_func, it returns '204'. Looks like 'value' might be reset after being printed?! I'm not sure. Many thanks to hk_mp5kpdw, that was a lot of help so far, Cheers

    Oh, and I knew about the printf/sprintf/cout thing. I made this project as a test from a bunch of code from a larger project. Sprintf was writing things to the buffer, then the buffer was being output to a file in the form of a log.

  4. #4
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,817
    Quote Originally Posted by xconspirisist
    If you see, in test_func, it returns '204'. Looks like 'value' might be reset after being printed?! I'm not sure.
    Well, it looks like you've changed the type of value from an int to a bool so why are you printing out an int in the printf? Test if value is true, if so, then output "true", else output "false".

    It is not being reset after being printed. You are creating a new instance of the myclass_t object in the test_func function without initializing the value data member. Whatever random junk was in the memory location now occupied by the value member is what will determine its value unless you first call the set member function.

    You can do this... Create a constructor for your myclass_t class. Then, either call the set function from within that constructor, or just set value to true.

    #1
    Code:
    myclass_t::myclass_t()
    {
        set();
    }
    #2 - Or...
    Code:
    myclass_t::myclass_t()
    {
        value = true;
    }
    #3 - Or...
    Code:
    myclass_t::myclass_t() : value(true)
    {
    }
    #4 - Or... combine constructor argument with a default argument
    Code:
    myclass_t::myclass_t(bool init = true) : value(init)
    {
    }
    The last two (#3/#4 using the initializer list) would be the prefered forms. The last one allows you to create an object and specify a starting value for the value data member so you can do things like:

    Code:
    myclass_t c1;        // Default value set to true
    myclass_t c2(true);  // Explicitly set to true
    myclass_t c3(false); // Explicitly set to false
    In any case, now whenever you create an instance of a myclass_t object, the default value stored in the value data member will be true.
    "Owners of dogs will have noticed that, if you provide them with food and water and shelter and affection, they will think you are god. Whereas owners of cats are compelled to realize that, if you provide them with food and water and shelter and affection, they draw the conclusion that they are gods."
    -Christopher Hitchens

  5. #5
    Registered User xconspirisist's Avatar
    Join Date
    Nov 2003
    Posts
    44
    That is a great deal of help. From that, how can I allow the value of 'value' to be carried across functions?

    Some psudo code:

    Code:
    void test_func ( void ) { 
    	myclass_t myclass_h;
    	
    	if ( myclass_h.read_value() ) {
    		cout << "Value is true.";
    	} else {
    		cout << "Value is false.";
    	}
    
    }
    
    int main(int argc, char* argv[])
    {
    	myclass_t myclass_h;
    
    	myclass_h.set ();
    
    	if ( myclass_h.read_value() ) {
    		cout << "Value is true.";
    	} else {
    		cout << "Value is false.";
    	}
    
    	myclass_h.unset ();
    
    	if ( myclass_h.read_value() ) {
    		cout << "Value is true.";
    	} else {
    		cout << "Value is false.";
    	}
    
    	myclass_h.set();
    
    	test_func() ;
    
    }
    If you see, in the main function it is calling 'set', to set the value to true. Now, when test_func is called the value is false. You explain that this is because I am creating a new 'insance', in test func...

    Code:
    	myclass_t myclass_h;
    Which calls the constructor, which sets the value to default false.

    I dont want the value to default to false, insted, erm, remeber that the value was set to true in the main func.

    I cant thank you enough for your responses.




    ---




    EDIT: I believe I have solved the issue! By creating a 'global instance' (?), placing

    Code:
    	myclass_t myclass_h;
    at the top of the file, not within a function, the constructor is not recalled, and the value retains the correct value!

  6. #6
    Registered User
    Join Date
    Apr 2003
    Posts
    2,663
    Two objects of a class are independent of each other. They each have their own member variables and member functions.

    I dont want the value to default to false, insted, erm, remeber that the value was set to true in the main func.
    The member variable of an object has the same value inside all the member functions for that object. However, if you create another object, it has no knowledge of the first object. It only has knowledge of its own member variables and member functions.

  7. #7
    Registered User
    Join Date
    Apr 2003
    Posts
    2,663
    EDIT: I believe I have solved the issue! By creating a 'global instance' (?), placing
    Unfortunately, that's the wrong approach. As a general rule, especially when you are starting out, don't ever use global variables. Back to the drawing board.

  8. #8
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,817
    The instance of myclass_h in main is completely different from the one in your test_func function. They are two seperate/unique objects as far as the program is concerned. I believe what you mean to do is pass the instance of myclass_h that exists in main into the test_func function. To do this, the function needs to accept an argument of type myclass_t and when you call the function from within main, you will pass myclass_h as the argument. Within the test_func function you would not create a new instance of the class but rather use the one passed in as the argument.

    Code:
    void test_func ( myclass_t myclass_h ) { 
    	
        if ( myclass_h.read_value() ) {
            cout << "Value is true.";
        } else {
            cout << "Value is false.";
        }
    
    }
    
    int main(int argc, char* argv[])
    {
        myclass_t myclass_h;
    
        myclass_h.set ();
    
        if ( myclass_h.read_value() ) {
            cout << "Value is true.";
        } else {
            cout << "Value is false.";
        }
    
        myclass_h.unset ();
    
        if ( myclass_h.read_value() ) {
            cout << "Value is true.";
        } else {
            cout << "Value is false.";
        }
    
        myclass_h.set();
    
        test_func( myclass_h ) ;
    
    }
    How you actually end up passing the object, by copy (as demonstrated above) or by reference, will depend on whether or not you wish to modify the object within the function and have the modifications to said object persist outside of the called function.
    "Owners of dogs will have noticed that, if you provide them with food and water and shelter and affection, they will think you are god. Whereas owners of cats are compelled to realize that, if you provide them with food and water and shelter and affection, they draw the conclusion that they are gods."
    -Christopher Hitchens

  9. #9
    Registered User xconspirisist's Avatar
    Join Date
    Nov 2003
    Posts
    44
    Okey then. Consider this code:

    Code:
    void func_2 ( myclass_t myclass_h ) {
        myclass_h.value = false;
    }
    
    void func_1 ( myclass_t myclass_h ) {
        // this is some sort of looping function, that calls func_2 many times...
        // this func does not use myclass_h
        func_2 ( myclass_h );
    }
    
    int main(int argc, char* argv[])
    {
        myclass_t myclass_h;
    
        myclass_h.value = true;
    
        return 0;
    }
    Presume that main is not allowed to call func_2
    Does this mean, if the class is initialised in main, that they only way to use it in func_2, is to pass it to func_1, then onward to func_2?

    If I shouldent use a global variable at the top of the file:

    Code:
    myclass_t myclas_h
    Because apparently global variables are bad, also, I would have no way of accessing it from any other file.

    If I declare it in a header, presumably so all files could access it, in the method above I'll get errors during link, about the variable already being defined...
    Last edited by xconspirisist; 06-16-2005 at 07:43 AM.

  10. #10
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,817
    Quote Originally Posted by xconspirisist
    Presume that main is not allowed to call func_2
    Does this mean, if the class is initialised in main, that they only way to use it in func_2, is to pass it to func_1, then onward to func_2?
    If the object is not global and was instantiated within main, then the only way to use it in func_2 is for it to have been passed into the function starting from main and then through func_1.

    Quote Originally Posted by xconspirisist
    If I shouldent use a global variable at the top of the file:

    Code:
    myclass_t myclas_h
    Because apparently global variables are bad, also, I would have no way of accessing it from any other file.

    If I declare it in a header, presumably so all files could access it, in the method above I'll get errors during link, about the variable already being defined...
    Accessing it from another file? You mean you have a multi-source file program and you are instantiating an object in one of the source files and need to use it in another source file? If all the source files include the header file that holds the description of the class then there should be no problem with having a function in one of the other source files that accepts an argument of that class/type, you just end up passing the object from function-to-function regardless of what source file the function is defined in.

    Class.H
    Code:
    #ifndef CLASS_H
    #define CLASS_H
    
    class myclass_t
    {
        bool value;
    public:
        ...
    };
    
    #endif
    Func.Cpp
    Code:
    // Include Class.H so this source file knows what a myclass_t object looks like
    #include "Class.H"
    
    void func(myclass_t myclass_h )
    {
        // Do stuff with myclass_h passed in from other source file
    }
    Main.Cpp
    Code:
    // Include Class.H so this source file knows what a myclass_t object looks like
    #include "Class.H"
    
    // Prototype function defined in other source file as extern
    // You could put this prototype in a header of its own if needed
    extern void func(myclass_t);
    
    int main()
    {
        myclass_t myclass_h;  // Create an instance of a myclass_t object
    
        func(myclass_h);      // Call function defined in other source file
    
        return 0;
    }
    [edit]
    Code:
    if ( myclass_h.read_value() ) {
        cout << "Value is true.";
    } else {
        cout << "Value is false.";
    }
    If you are going to be doing this sort of thing often, you might want to just overload the stream insertion << operator:

    Code:
    #include <iostream>
    
    class myclass_t
    {
        ...
        friend std::ostream& operator<<(std::ostream& os,const myclass_t& rhs);
    };
    
    ...
    
    std::ostream& operator<<(std::ostream& os,const myclass_t& rhs)
    {
        if ( rhs.value ) os << "Value is true.";
        else os << "Value is false.";
        return os;
    }
    Then you can just say:
    Code:
    myclass_t myclass_h;
    
    myclass_h.set();
    std::cout << myclass_h << std::endl;  // Outputs "Value is true"
    
    myclass_h.unset();
    std::cout << myclass_h << std::endl;  // Outputs "Value is false"
    [/edit]
    Last edited by hk_mp5kpdw; 06-16-2005 at 08:40 AM.
    "Owners of dogs will have noticed that, if you provide them with food and water and shelter and affection, they will think you are god. Whereas owners of cats are compelled to realize that, if you provide them with food and water and shelter and affection, they draw the conclusion that they are gods."
    -Christopher Hitchens

  11. #11
    Registered User xconspirisist's Avatar
    Join Date
    Nov 2003
    Posts
    44
    Sure. However, there are many functions that might use myclass, is there a more efficent way of using this class, with 'value' remaining as it were last set, without having it passed around in this way?

  12. #12
    Registered User xconspirisist's Avatar
    Join Date
    Nov 2003
    Posts
    44
    - double post -

  13. #13
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,817
    Quote Originally Posted by xconspirisist
    Sure. However, there are many functions that might use myclass, is there a more efficent way of using this class, with 'value' remaining as it were last set, without having it passed around in this way?
    Without making your objects global? No, your going to have to pass it amongst your functions. Passing by reference is more efficient than passing by copy. Having global objects may make things easier but is considered to be sloppier.
    "Owners of dogs will have noticed that, if you provide them with food and water and shelter and affection, they will think you are god. Whereas owners of cats are compelled to realize that, if you provide them with food and water and shelter and affection, they draw the conclusion that they are gods."
    -Christopher Hitchens

  14. #14
    Registered User xconspirisist's Avatar
    Join Date
    Nov 2003
    Posts
    44
    Now I'd like to ask you how to use a reference properly. I fiddeled for 10 minutes, and did a lot of googling to no avail.

    Cearly this thread could contine many pages long with my seemingly annoying questions. I cant thank you enough for the help so far, although It is obviously not a small problem, and my knowledge of C++ is so very lacking that the only way to solve this appears to be by getting a very large programming book.

    Again, thank you all so very much, hk_mp5kpdw, you in particular have been very, very helpfull.

    Now, who can reccommend a good book?

  15. #15
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,817
    In terms of function arguments:
    Code:
    void func(int & val)  // The "&" means val is a reference parameter/ an alias for the incomming argument
    {
        val = 100;
    }
    
    int main()
    {
        int myint = 50;
    
        func(myint);     // After function call, myint = 100
    
        return 0;
    }
    You can do the same thing with pointers but the syntax becomes just a tiny bit more involved:
    Code:
    void func(int * val)
    {
        *val = 100;
    }
    
    int main()
    {
        int myint = 50;
    
        func(&myint);
    
        return 0;
    }
    If you aren't specifically talking about function arguments then:
    Code:
    int i = 50;
    
    cout << i << endl;  // Prints 50
    
    int & tempref;      // By itself this is illegal since a reference must be initialized to something when created
    int & ref = i;      // Create an integer reference named "ref" that is an alias for "i"
    ref = 100;          // Changes "ref"/"i" to 100
    
    cout << i << endl;  // Prints 100
    Again, you can duplicate the effect using pointers with a tiny bit of extra syntax to work with:
    Code:
    int i = 50;
    
    cout << i << endl;  // Prints 50
    
    int * tempref;      // By itself this is fine unlike for a reference
    int * ref = &i;     // Create an integer pointer named "ref" that points to the memory address of "i"
    *ref = 100;         // Changes value pointed to by "ref", i.e. "i" to 100
    
    cout << i << endl;  // Prints 100
    Last edited by hk_mp5kpdw; 06-16-2005 at 12:52 PM.
    "Owners of dogs will have noticed that, if you provide them with food and water and shelter and affection, they will think you are god. Whereas owners of cats are compelled to realize that, if you provide them with food and water and shelter and affection, they draw the conclusion that they are gods."
    -Christopher Hitchens

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Class design problem
    By h3ro in forum C++ Programming
    Replies: 10
    Last Post: 12-19-2008, 09:10 AM
  2. deriving classes
    By l2u in forum C++ Programming
    Replies: 12
    Last Post: 01-15-2007, 05:01 PM
  3. Message class ** Need help befor 12am tonight**
    By TransformedBG in forum C++ Programming
    Replies: 1
    Last Post: 11-29-2006, 11:03 PM
  4. Replies: 3
    Last Post: 10-31-2005, 12:05 PM
  5. Warnings, warnings, warnings?
    By spentdome in forum C Programming
    Replies: 25
    Last Post: 05-27-2002, 06:49 PM