Beginner Needs Help with Classes and Functions

Started by
4 comments, last by shawnre 16 years, 10 months ago
Hello once again guys/gals, Once again I am having trouble following along with the C++ workshop. We had to write a program that allows the user to select what color to display a menu. At first I tried doing this in a separate class header file with an associated cpp file showing the definitions of the class. That utterly failed. I am sure there is something within the book that I am just misunderstanding. Anyhow, I managed to get a little program together that worked a little bit. Now, the dilemma I am facing is, taking my short program below, that I will modify to fit the appropriate 15 color options after I figure out how to separate them, lol. Anyhow, here is what I have, and I am trying to figure out how to seperate the class declaration and definitions into separate .h and .cpp files from the main. Can anyone show me how to do that, and possibly comment on the process of it. I am unable to say exactly what it is I am not connecting together, but, I have up to this point been unable to do it. Thanks for any help, Shawn

//Main for the Menu system

#include <iostream>
#include <windows.h>

using namespace std;


	//The following declares a class called Menu
	
	class Menu
	{
	public:
		void ChangeColor(int);
	};

	//The following defines ChangeColor of class Menu

	void Menu::ChangeColor(int color)
	{
		HANDLE hConsole = GetStdHandle( STD_OUTPUT_HANDLE );
		SetConsoleTextAttribute( hConsole, color ); // where color is the color code to set it to
		
	}

	int main()
	{
		cout<<"Menu"<<endl;
		Menu Color;
		//HANDLE hConsole = GetStdHandle( STD_OUTPUT_HANDLE );
		Color.ChangeColor(2);
		cout<<"Menu"<<endl;
		Color.ChangeColor(15);
		cout<<"Menu"<<endl;
	}

Advertisement
Generally, you would put the definition of the class and its methods in the header file, and then include that in to all files that need to 'know' about that class.

In this situation, the Menu class definition would go in the header file, and be included in the file with the implementation.

Menu.h: Included in all files that want to know about the Menu class

class Menu{public:    void ChangeColor(int);};


Menu.cpp: Contains the implementation of the ChangeColor() method

#include "Menu.h"void Menu::ChangeColor(int color){    HANDLE hConsole = GetStdHandle( STD_OUTPUT_HANDLE );    SetConsoleTextAttribute( hConsole, color ); // where color is the color code to set it to		}


Main.cpp: The compiler already has the implementation of the class method from Menu.cpp, so you only have to include Menu.h here so Main.cpp 'knows' about the class and how to use it

#include <iostream>#include <windows.h>#include "Menu.h"using namespace std;int main(){	cout<<"Menu"<<endl;	Menu Color;	Color.ChangeColor(2);	cout<<"Menu"<<endl;	Color.ChangeColor(15);	cout<<"Menu"<<endl;}


Edit: Fixed source

[Edited by - ChristmasCelery on June 1, 2007 12:36:56 PM]
Quote:Original post by ChristmasCelery
Generally, you would put the definition of the class and its methods in the header file, and then include that in to all files that need to 'know' about that class.

In this situation, the Menu class definition would go in the header file, and be included in the file with the implementation.


Er, "declaration". The definition is where you flesh out the class functions (in the source file (.cpp))

OP: All you are really doing is placing the class declarations, or "blueprints" in the header files, and doing the actual "coding work" in the .cpp files.

In the .cpp file, you must always include the header that declares each of the classes/functions you will be using.

// in myclasses.cpp#include "myclasses.h"


In that way the compiler will know how to construct a class object from your class, and what class functions it will find.

Later, if you want to use those classes in another project, simply include that ".h" file again, add the .cpp file to your project, and you're good to go.

The .cpp file functions as a sort of "black box" with respect to other .cpp files and headers. The stuff that is "visible" is usually in the header (.h/.hpp) file.
my_life:          nop          jmp my_life
[ Keep track of your TDD cycle using "The Death Star" ] [ Verge Video Editor Support Forums ] [ Principles of Verg-o-nomics ] [ "t00t-orials" ]
Thanks guys, your explanations have helped me I believe get a handle on class in a .h file with their definitions in the .cpp. I managed to finish the project, however I still have some problems with it. If anyone could look into this thread, should be the last post, and offer me any advice it would be appreciated. I would just repost here, but, not sure if that is an appropriate thing to do; ie having a double post of the same info.

1. As I said in that thread, I needed some way to break my while loop in the main, and the only way I could think how to do it was to use the if's in the main. There must be a better way to do that right?

2. After testing a bit more, my validation of the users input does not seem to be functioning as I expected. Valid choices should be between 1 and 16, however, when the user enters something higher than 16, it prints the error, but also changes the color anyhow.....any suggestions how to fix that?

3. Originally jwalsh had suggested we use an enum for the colors. I have it defined, but wasnt sure exactly how/why/where I would use it...

Thanks for any help, I am not asking you to do it for me, just offer me some tips on where/what I should proceed with. The more I actually do it myself, the better I seem to be grasping the material. Here is the thread link:

LINK

Thanks,

Shawn

*Edit* - If you see any errors in syntax, or how I did something, ie a "better way" please point that out also. Like mentioned in the title, I am a beginner and am definitely trying to learn this language correctly. Thanks again!
Quote:Original post by shawnre
1. As I said in that thread, I needed some way to break my while loop in the main, and the only way I could think how to do it was to use the if's in the main. There must be a better way to do that right?

Well, there's the 'break' statement, but you still need an if and this way is just a little more flexible as you can only break out of one loop at a time. Besides the break statement, you could just put return 0; in the if statement, but you shouldn't. It's generally more appropriate to only have one return statement in your code, at the bottom of the function, if possible.

Quote:2. After testing a bit more, my validation of the users input does not seem to be functioning as I expected. Valid choices should be between 1 and 16, however, when the user enters something higher than 16, it prints the error, but also changes the color anyhow.....any suggestions how to fix that?


Well, look at the steps you are performing. You get the user's input, then you check if it was in the range, and then you call the function to change the colors. There's no deviation from this path because you never change the course of action based on what the user entered. You need a way to skip that step based on the user entered info. Probably by using another if statement :) Actually, a better suggestion is to move the location of your input validation into the get_input function. you check if the input is valid and if it isn't you loop and ask the user for the correct input. Make sense?

Quote:3. Originally jwalsh had suggested we use an enum for the colors. I have it defined, but wasnt sure exactly how/why/where I would use it...

The difficulty with this problem is it's not necessary to use enums so it probably makes it harder to see why you should use them. Mainly because, in this case, it results in extra code, not less. I'll show a few lines and hopefully that will let you figure out what you should do:

switch(color){  case DarkBlue: // set color here                 break;  case DarkGreen: // set color here                  break;  // etc  case Quit: // quit here}


Now for the code critiquing.

1. Your file name for the header file is MenuClass.h, but you name your cpp file MenuFunctions.cpp. You should try and keep the names of the header and implementation file the same as then you can easily tell which files correspond to each other. So make the implementation file MenuClass.cpp instead.

2. Your header file includes the using namespace std; line. Take it out! You should never put this in a header file because you can't get ride of a using namespace std; declaration once you give it. Instead, qualify every time you use something from the std namespace. You don't use anything from the std namespace so you don't have to change anything! While your at it get rid of #including iostream as you don't use that either.

3. Add include guards for the header file. There's no problem now, but when you get more complicated programs you could get errors (including the same thing twice on accident usually). You can add include guards easily. At the top of each header file add these two lines:

#ifndef FILENAME_H_
#define FILENAME_H_

where filename is the name of your header file. Then, at the very bottom of the header add #endif. What this does is check if the symbol FILENAME_H_ exists, if it does, it does nothing until it finds #endif. Otherwise, it will make the symbol FILENAME_H_ exist and allow the compiler to see the code after that. Make sense?

4. Every time you call the method ChangeColor you get the handle for the console. That strikes me as unneeded. This is a perfect opportunity to create a constructor and use that to get the handle and you can store the handle into a member variable. Then, in ChangeColor, you use the saved handle directly without calling the GetStdHandle function.

5. If you're still looking for ways to do this program then read some of the other people's responses to the quiz. This will show all the different ways people have done the exercises and hopefully give you ideas.

Lastly, here's what I'd have done based on your code(only look after you've gotten your own program to work better):
Menuclass.h
#ifndef MENUCLASS_H_#include <windows.h>// The menu class provides functionality to display the menu, get and validate user// input, and to change the text colorclass Menu{	HANDLE hConsole;public:	Menu();	void DisplayMenu();	unsigned short GetInput();	void ChangeColor(unsigned short);  // Function to change text color	bool InvalidInput(unsigned short);		enum MenuColor {DarkBlue=1, DarkGreen, Teal, Burgundy, Violet, Gold, Silver, Gray, Blue, Green, Cyan, Red, Purple, Yellow, White, Quit};};#endif

MenuClass.cpp
//This file is the definitions of the MenuClass.h//MenuClass.cpp#include "MenuClass.h"#include <iostream>#include <windows.h>using namespace std;Menu::Menu(){	hConsole = GetStdHandle( STD_OUTPUT_HANDLE );}//The following defines ChangeColor of class Menuvoid Menu::ChangeColor(unsigned short color){	switch(color)	{		case Menu::Blue:		{			SetConsoleTextAttribute( hConsole, Menu::Blue);			break;		}		case Menu::Burgundy:		{			SetConsoleTextAttribute( hConsole, Menu::Burgundy);			break;		}		case Menu::Cyan:		{			SetConsoleTextAttribute( hConsole, Menu::Cyan);			break;		}		case Menu::DarkBlue:		{			SetConsoleTextAttribute( hConsole, Menu::DarkBlue);			break;		}		case Menu::DarkGreen:		{			SetConsoleTextAttribute( hConsole, Menu::DarkGreen);			break;		}		case Menu::Gold:		{			SetConsoleTextAttribute( hConsole, Menu::Gold);			break;		}		case Menu::Gray:		{			SetConsoleTextAttribute( hConsole, Menu::Gray);			break;		}		case Menu::Green:		{			SetConsoleTextAttribute( hConsole, Menu::Green);			break;		}		case Menu::Purple:		{			SetConsoleTextAttribute( hConsole, Menu::Purple);			break;		}		case Menu::Red:		{			SetConsoleTextAttribute( hConsole, Menu::Red);			break;		}		case Menu::Silver:		{			SetConsoleTextAttribute( hConsole, Menu::Silver);			break;		}		case Menu::Teal:		{			SetConsoleTextAttribute( hConsole, Menu::Teal);			break;		}		case Menu::Violet:		{			SetConsoleTextAttribute( hConsole, Menu::Violet);			break;		}		case Menu::White:		{			SetConsoleTextAttribute( hConsole, Menu::White);			break;		}		case Menu::Yellow:		{			SetConsoleTextAttribute( hConsole, Menu::Yellow );			break;		}		default:		{			break;		}	}// end switch}//This will display the menuvoid Menu::DisplayMenu(){	cout<<"Color Selection Menu:" <<endl <<endl;	cout<<"1. Dark Blue"<<endl;	cout<<"2. Dark Green"<<endl;	cout<<"3. Teal"<<endl;	cout<<"4. Burgundy"<<endl;	cout<<"5. Violet"<<endl;	cout<<"6. Gold"<<endl;	cout<<"7. Silver"<<endl;	cout<<"8. Gray"<<endl;	cout<<"9. Blue"<<endl;	cout<<"10. Green"<<endl;	cout<<"11. Cyan"<<endl;	cout<<"12. Red"<<endl;	cout<<"13. Purple"<<endl;	cout<<"14. Yellow"<<endl;	cout<<"15. White"<<endl;	cout<<"16. Quit"<<endl<<endl;}//Function to get the users inputunsigned short Menu::GetInput(){	unsigned short choice;	do	{		cout<<"Please enter a choice for your color: ";		cin>>choice;	}while( InvalidInput(choice) );		return choice;}//Function to validate the users inputbool Menu::InvalidInput(unsigned short choice){	if ((choice<1) || (choice>16))	{		cout << "Error, choice must be between 1 and 16" << endl;		return true;	}	return false;}

Main.cpp
//Main for the Menu system#include <iostream>#include "MenuClass.h"using namespace std;int main(){	bool Exit=false;	while (!Exit)	{		Menu UserMenu;		UserMenu.DisplayMenu();		unsigned short Choice = UserMenu.GetInput();		if(Choice == Menu::Quit)		{			Exit = true;		}		else		{			UserMenu.ChangeColor(Choice);		}			}}

C++: A Dialog | C++0x Features: Part1 (lambdas, auto, static_assert) , Part 2 (rvalue references) , Part 3 (decltype) | Write Games | Fix Your Timestep!

Thanx nobodynews, appreciate the feedback. I am not gonna check your code at the bottom until I go back and rework my code a bit more, and also, as you suggested look at some of the others code in that thread.

Thanks,

Shawn

This topic is closed to new replies.

Advertisement