Global Variables in C++?

This is a discussion on Global Variables in C++? within the C++ Programming forums, part of the General Programming Boards category; Hi, I'm just starting C++ but I've done quite a bit in Java and VB . I've learnt a lot ...

  1. #1
    DeX
    DeX is offline
    Infected Coder DeX's Avatar
    Join Date
    Sep 2004
    Location
    Cardiff, Wales
    Posts
    7

    Global Variables in C++?

    Hi,

    I'm just starting C++ but I've done quite a bit in Java and VB. I've learnt a lot over the last few days from all the tutorials and books and MSDN of course, but the thing I'm finding hardest to learn is not how to program but how to make programs .

    What I mean is when I'm writing code I never know if what I'm doing is the 'right' thing to do or if there are better ways to do what I want. I try to think about the best object-oriented way to accomplish certain tasks.

    Anyway the problem I have at the moment is that I want to create an object which will exist for the duration of the program. I want to construct the object when the program starts (IE when the WM_INITDIALOG message is sent). But I want to be able to access the object at other times during the program's excecution such as when the user clicks on the window. At the moment I have this code:

    Code:
    HDC hdc = GetDC(hWnd);
    MapTiler mp(hdc,100,4,4);
    ReleaseDC(hWnd,hdc);
    This works fine but as soon as the DialogProc ends the object goes out of scope and is destroyed.

    Is there a way I can decalare the object outside of the DialogProc scope so that I can access it at any time? Note that I have to call the object's constructor while passing the HDC of the window as a parameter. In Java this would be easy. I could declare the object as an attribute of the program's class and then instantiate it when the program started. It seems though that C++ requires you to instantiate the object at the same time as declaring it which means I can't declare the object outside the scope DialogProc and instantiate it inside the DialogProc scope.

    What is the best way to get around this? Should I use a pointer to the object? Should I use a global variable at all? In my opinion using global variables is not a very object-oriented technique so maybe there's an entirely different way of doing this.

  2. #2
    Registered User
    Join Date
    Apr 2003
    Posts
    2,662
    First, what you are asking about is called "windows programming". Windows programs have a very different structure than console type programs, and therefore there is a separate forum for windows programming.

    It seems though that C++ requires you to instantiate the object at the same time as declaring it
    Yes, that's true, but you can use pointers:

    Obj* p;
    ...
    ...
    //sometime later:
    p = new Obj(1, 2, 3);

    I think pointers and java references are essentially the same thing. The key aspect for both is that when multiple variables refer to the same object, and you change that object, then all the variables change.


    In Java this would be easy. I could declare the object as an attribute of the program's class and then instantiate it when the program started.
    What's the difference:

    Java:
    Code:
    class Obj
    {
    	String color;
    
    	Obj(String c)
    	{
    		color = c;
    	}
    	
    	Obj()
    	{
    		color = "";
    	}
    }
    
    class Program
    {
    	Obj obj;
    	int size;
    
    	Program(String c, int b)
    	{
    		obj = new Obj(c);
    		size = b;
    	}
    };
    
    class DemoProgram
    {
    	public static void main(String[] args) 
    	{
    		Program my_program = new Program("red", 10);
    		System.out.println(my_program.obj.color);
    	}
    }
    C++:
    Code:
    #include<iostream>
    #include<string>
    using namespace std;
    
    class Obj
    {
    public:
    	string color;
    
    	Obj(string c)
    	{
    		color = c;
    	}
    	
    	Obj()
    	{
    		color = "";
    	};
    
    	
    };
    
    class Program
    {
    public:
    	Obj obj;
    	int size;
    
    	Program(string c, int b)
    	{
    		obj = Obj(c);
    		size = b;
    	}
    };
    
    int main()
    {
    	
    	Program my_program("red", 10);
    	cout<<my_program.obj.color<<endl;
    
    	return 0;
    }
    Last edited by 7stud; 03-10-2005 at 01:59 PM.

  3. #3
    DeX
    DeX is offline
    Infected Coder DeX's Avatar
    Join Date
    Sep 2004
    Location
    Cardiff, Wales
    Posts
    7
    Quote Originally Posted by 7stud
    First, what you are asking about is called "windows programming". Windows programs have a very different structure than console type programs, and therefore there is a separate forum for windows programming.
    That's one of the difficult things for me. Most books and tutorials seperate Windows programming and C++ programming. I don't want to get into MFC just yet but at the moment I find it relatively difficult to combine what I learn about the one subject with the other. All I want to do is create a standard 'C' Windows program that uses classes. Anyway I felt this had more to do with OO than Windows programming.

    Quote Originally Posted by 7stud
    Yes, that's true, but you can use pointers:
    Ok so you think pointers are the best way to do it? I ask because as far I can tell from what I've learnt so far there are two main ways to create objects:

    First way (don't know what it's called):
    Code:
    MapTiler mp(hdc, 100, 4, 4);
    which creates a variable mp which is a reference to an instance of the MapTiler class.

    And the second way using new:
    Code:
    MapTiler *mp = new MapTiler(hdc, 100, 4, 4);
    Which creates a pointer to an instance of the MapTiler class.

    Now in my opinion it would be better to have a reference rather than a pointer to the object. That way I can use the . operator rather than the -> operator to access member attributes and functions. Also I don't have to delete the object when I'm finished with it (or do I?). And also because of the way Java hides pointers from you the reference way seems better (coming from a Java point of view). I've not found any books or tutorials that discuss these two methods and their advantages and disadvantages.

    Also what about the global variable thing. Is it normal for programs to list all the objects they want to declare in the main program section (the bit before any functions appear)?

  4. #4
    Registered User
    Join Date
    Mar 2002
    Posts
    1,595
    >>MapTiler mp(hdc, 100, 4, 4);

    mp here is a static variable whereas here

    >>MapTiler *mp = new MapTiler(hdc, 100, 4, 4);

    mp is a dynamic variable, or they would be if you describe based on the type of memory used to reserve space for them. In the first case mp is created on the stack using static memory, whereas in the second case mp is a pointer to a variable of type MapTiler of undefined name stored on the heap (aka free store) using dynamic memory and unnamed variable is only accessable at this point using the pointer called mp. The following would create a variable called mp and a reference called rMP which "points" (aka refers) to mp and can be used like mp.

    MapTiler mp(hdc, 100, 4, 4);
    MapTiler & rMP = mp;

    That means variables, pointers, and references are three different, but related things.

    You should also know that C is a language that can't use classes, or an Object Oriented approach, like C++ can. Windows programming is generally done using the Windows API which is written in C, though C++ syntax can be used to accomplish the same thing most of the time. MFC (and other libraries like VCL in Borland) is a proprietary library (not a complete language in itself, but the Windows API isn't a complete language in itself either) that basically wraps the Windows API in C++ classes, etc.

    And, yah, it is a pretty convoluted interwoven scene, but you get used to it after a while.
    You're only born perfect.

  5. #5
    Registered User
    Join Date
    Apr 2003
    Posts
    2,662
    That's one of the difficult things for me. Most books and tutorials seperate Windows programming and C++ programming. I don't want to get into MFC just yet but at the moment I find it relatively difficult to combine what I learn about the one subject with the other.
    C++ is a prerequisite to windows programming and MFC, although if you have a lot of object orientated programming experience, you can probably wade right into it. Personally, I think the MFC is pretty confusing, but I only have a beginning understanding of C++.

    I suggest you start with a C++ book. Actually, I have a pretty good book that gives a relatively short overview of C++(v. the 900+ page Beginning C++ book I also have)--which may be what you are after with your Java background--and then moves into Windows programming. It's called, "Ivor Horton's Visual C++ 6". The first 12 chapters are on C++, and the next 12 are on windows programming with the MFC. Usually, C++ books are called something like "Learn C++ in 5 Seconds" where a windows programming book will be titled something like: Learn Visual C++ in 33 seconds" or "Windows Programming and the MFC--Learn it all while you Sleep".

    ..as far I can tell from what I've learnt so far there are two main ways to create objects: First way (don't know what it's called):
    Code:
    MapTiler mp(hdc, 100, 4, 4);
    which creates a variable mp which is a reference to an instance of the MapTiler class.
    That's generally called 'statically' creating an object, and the compiler sets aside the memory for the object before the program runs. Objects declared like that go out of scope and are destroyed when the block they are declared in, i.e the enclosing braces {}, ends. For instance, a statically declared array is a good example of such an object:
    Code:
    int main()
    {
    	if(true)
    	{
    		int my_array[10];
    		my_array[0] = 1;
    		my_array[1] = 100;
    		cout<<my_array[0]<<endl;
    	}
    
    	cout<<my_array[0]<<endl;  //error
    
    	return 0;
    }
    Code:
    MapTiler mp(hdc, 100, 4, 4);
    which creates a variable mp which is a reference to an instance of the MapTiler class.
    However, it is not like a java reference(or a C++ pointer). A java reference or C++ pointer stores an address of an object in memory. But, check out this code:
    Code:
    class Obj
    {
    public:
    	string color;
    
    	Obj(string c)
    	{
    		color = c;
    	}
    	
    	Obj()
    	{
    		color = "";
    	}
    	
    };
    
    int main()
    {
    	Obj obj("blue");
    	cout<<sizeof obj<<"\n";  //16
    
    	Obj* p = &obj; //assign the address of obj to p
    	cout<<sizeof p<<endl;  //4
    
    	return 0;
    }
    If obj was a reference/pointer, then it's size would be the same size as the pointer, but their sizes are 16 and 4 respectively. obj is actually the object itself which takes up 16 bytes in memory, and p is a variable somewhere else in memory that stores the address of obj, and the address only takes up 4 bytes.

    And the second way using new:
    Code:
    MapTiler *mp = new MapTiler(hdc, 100, 4, 4);
    Which creates a pointer to an instance of the MapTiler class.
    That's called 'dynamically' creating an object. Notice you can't give the object a name--otherwise the compiler would try to set aside memory for the object. It's 'dynamic' because the memory is not allocated for the object until 'run time', i.e. when the statement is actually executed. The most important implication for dynamically allocating memory is that the object does not go out of scope when the enclosing block ends--as it does with a 'statically' declared object. In Java, all objects are dynamically created.

    In C++, whenever you use the new operator, you have to use the delete operator to free up the memory. When your program ends the memory is freed up automatically, but while it is running you can create memory leaks that will overwhelm your system. On the other hand, Java frees up the memory automatically, i.e. 'garbage collection', when there are no longer any references to the object(or at some point thereafter). However, that requires additional overhead to constantly check for references to an object, which slows a program down, and slowing a program down is considered treason in C++. Also, since there is no garbage collection in C++, it is considered the height of bad form to no longer have a reference to an object. If you do something like this:

    Obj* p = new Obj(1,2,3);
    p = 0;

    ...then there is no way to ever reference the object again, and since there is no garbage collection in C++, the object will sit in memory taking up room needlessly until your program ends and the memory is released. Inefficient...inefficient...inefficient! In C++, the correct thing to do is, first, not lose references to objects that you need, and, second if you don't need an object created with the new operator anymore, then you delete it. Objects not created with the new operator will automatically be removed from memory when they go out of scope.

    The advantage of dynamically allocating memory is that you can allocate the exact amount you need. For instance, if you need to put some user input into an array, but you don't know how many items the user will enter, then if the array were statically declared, you would have to guess the maximum number of items, and make a declaration like this:

    int my_array[100];

    Now, if the user only ends up entering two elements, the compiler will have reserved more memory than your program needs, which is wasteful and can tax system resources. However, when you dynamically allocate memory, you can allocate only what you need:
    Code:
    int main()
    {
    	int* p;
    
    	if(true)
    	{
    		int size;
    		cout<<"enter how many integers you want in the array: ";
    		cin>>size;
    
    		p = new int[size];  //creates an array just big enough for the input
    
    		cout<<"enter your array elements: ";
    		for(int i = 0; i < size; i++)
    		{
    			cin>>p[i];  //you can use array notation with a pointer
    
    		}
    		
    		cout<<p[0]<<endl; 
    	}
    
    	cout<<p[0]<<endl; //the array still exists out here!
    
    	delete [] p;  //if a pointer points to an array, you use brackets before the name
    				  //Note: this delete is not strictly necessary since the next line ends
    				  //the program when the memory would be freed automatically anyway.
    
    	return 0;
    }

    Now in my opinion it would be better to have a reference rather than a pointer to the object. That way I can use the . operator rather than the -> operator to access member attributes and functions.
    You can always dereference the pointer *, put parenthesis around the whole thing, and then use the . operator, but since that is so clumsy, C++ has the -> operator, which of course is one more character to type than the . operator.

    Also I don't have to delete the object when I'm finished with it (or do I?).
    If you 'new', you have to 'delete'.

    Ok so you think pointers are the best way to do it? I ask because as far I can tell from what I've learnt so far there are two main ways to create objects:
    <gulp...as I reach for my windows programming book.> Ok, with MFC, I think you have to declare a class, e.g. CMyApp, in your program that represents your application and it derives from CWinApp. Since it derives from CWinApp, it has certain member variables automatically. Also, in your class CMyApp, you have to declare a method InitInstance() which overrides a virtual InitInstance() function, and inside your definition of InitInstance(), you have to initialize some of the inherited member variables in CMyApp with a window or dialog you create for your program, etc. I believe when your program starts up a CMyApp object is automatically instantiated, and the InitInstance() function is called.

    So....I think if you add a pointer to "that object you want to create" as a member variable of your CMyApp class, then in the InitInstance() function you can use the new operator to create one of your objects and assign it to that member pointer. Then, if any classes you create have a pointer to CMyApp, you can use that pointer to access the member pointer to your object.
    Last edited by 7stud; 03-10-2005 at 04:42 PM.

  6. #6
    DeX
    DeX is offline
    Infected Coder DeX's Avatar
    Join Date
    Sep 2004
    Location
    Cardiff, Wales
    Posts
    7
    Cool, thanks for all that info.

    I suppose then for this program I can create a global static instance of the MapTiler class using a default constructor and then modify all the various attributes when the program initialises. I could dynamically create the object but I'm only going to need one instance of it so I don't think there's much need.

    And I actually have Ivor Horton's Beginning Visual C++ 6. I haven't actually read it (it's pretty hefty) but I use it mainly for reference.

    Anyway this seems like a nice place to hang around. I will probably be back sooner or later with more queries.

  7. #7
    Registered User
    Join Date
    Apr 2003
    Posts
    2,662
    Quote Originally Posted by DeX
    And I actually have Ivor Horton's Beginning Visual C++ 6. I haven't actually read it (it's pretty hefty) but I use it mainly for reference.
    My MFC advice above is from p. 528 - 529.

  8. #8
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,893
    Completely unrelated to the primary discussion, but still a matter of the original post, this code:
    Code:
    HDC hdc = GetDC(hWnd);
    MapTiler mp(hdc,100,4,4);
    ReleaseDC(hWnd,hdc);
    Creates an invalid situation. The hdc that is passed to MapTiler and probably stored in that class is then released, making it invalid. Any subsequent access to the dc will fail.
    (The exception is if you have specified CS_OWNDC for the window class. In that case the code "works" because ReleaseDC is a no-op, but is still very fragile and not a good idea.)
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  9. #9
    DeX
    DeX is offline
    Infected Coder DeX's Avatar
    Join Date
    Sep 2004
    Location
    Cardiff, Wales
    Posts
    7
    Thanks for the feedback. It's always appriciated when errors in my code are pointed out.

    But in this situation what happens when the MapTiler is constructed is that it takes the HDC of the window that is passed to it. It then creates a memory DC that is compatible with the HDC using CreateCompatibleDC, then creates a compatible bitmap using CreateCompatibleBitmap and 'Selects' the bitmap into the memory DC. All this will be so that I can create a 'back buffer' upon which I will create an image using a bunch of tiles and which I can draw then onto the window during the WM_PAINT message.

    So I don't store the HDC of the window in the class and instead I store a compatible memory DC. When the class is destroyed the memory DC is deleted using DeleteDC and the bitmap is deleted using DeleteObject. Does that sound ok?

  10. #10
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,893
    Sounds fine.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 5
    Last Post: 08-06-2008, 09:59 AM
  2. scope of global variables
    By laertius in forum C++ Programming
    Replies: 4
    Last Post: 10-15-2006, 01:59 AM
  3. global variables - okay sometimes...?
    By MadHatter in forum C++ Programming
    Replies: 21
    Last Post: 01-21-2003, 03:23 PM
  4. global variables
    By rdnjr in forum Linux Programming
    Replies: 0
    Last Post: 01-07-2003, 09:28 AM
  5. Global variables? Bad! Yes, but to what extent?
    By Boksha in forum C++ Programming
    Replies: 6
    Last Post: 05-26-2002, 04:37 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21