having trouble calling a member function from a data structure

Started by
7 comments, last by laztrezort 14 years, 11 months ago
Hello. Below is a text-based rpg in the works. I had the functions and data types seperate from the Game class. However, I need the functions that are called by the command to be able to access various members of the Game class (such as Go, Exits, etc), so I decided to integrate them into the Game class. When trying to compile it, the first error I recieve is: error C2352: 'Game::split_into_words' : illegal call of non-static member function. If theres a better way to go about what I am trying to do I am all ears. Game.cpp:

#include "stdafx.h"
#include <string>
#include <iostream>
#include <vector>
#include <map>


struct Game::Command
{
	action a;
	Command(action a): a(a) {}
	void operator()(const std::string& command_line) 
	{
		a(split_into_words(command_line));
	}
};

std::string Game::first_word_of(const std::string& line)
{
	return line.substr(0, line.find(' '));		
}

std::string Game::rest_of(const std::string& line)
{
	std::string::size_type pos = line.find_first_of(" ");
	
	if (pos != std::string::npos)
	{
		return line.substr(pos + 1);
	}
	else 
	{
		return "";
	}	
}

// functions for the different commands
void Game::Go(const arguments& args) 
{
	if(args.size() == 0)
	{
		std::cout << "Please provide an exit with the go command.\n";
	}
	else
	{
		std::string exitToTake = args[0];
		Room& currentRoom = m_chameleon->GetPlayerLocation();
	}
}
void Game::Help(const arguments& args)
{
	
}
void Game::Quit(const arguments& args)
{
}
void Game::Exits(const arguments& args)
{
}
void Game::Save(const arguments& args)
{
}

std::vector<std::string> Game::split_into_words(const std::string& str)
{
	std::vector<std::string> words;
	// skip spaces at the beginning
	std::string::size_type lastPos = str.find_first_not_of(" ", 0);
	// find first non-space
	std::string::size_type pos = str.find_first_of(" ", lastPos);

	while(std::string::npos != pos || std::string::npos != lastPos)
	{
		// found a word, add it to the vector
		words.push_back(str.substr(lastPos, pos - lastPos));
		// Skip spaces.  
        lastPos = str.find_first_not_of(" ", pos);
        // Find next "non-space"
        pos = str.find_first_of(" ", lastPos);
	}
	return words;
}

std::string GetUserInput()
{
	std::cout << "Enter Command\n";
	std::cout << ">>";
	std::string line = "";
	std::getline(std::cin, line);
	return line;
}

void interpret_command(argument_mapping& mapping, const std::string& from_user) 
{
	std::string first_word = first_word_of(from_user);
	std::string command_line = rest_of(from_user);
	argument_mapping::iterator it = mapping.find(first_word);
	if (it != mapping.end()) 
	{
		(it->second)(command_line);				
	} 
}

argument_mapping GetGameCommands() 
{
	argument_mapping commands;
	commands.insert(std::pair<std::string, Command>("go", Go));
	commands.insert(std::pair<std::string, Command>("help", Help));
	commands.insert(std::pair<std::string, Command>("quit", Quit));
	commands.insert(std::pair<std::string, Command>("exits", Exits));
	commands.insert(std::pair<std::string, Command>("save", Save));
	return commands;
}

void Game::PlayGame()
{
	// object for helper functions
	GameHelpers gh;
	World world;
	CreateRooms(world);
	Room* startingRoom = &world[0];
	// make sure the memory is available.
	try 
	{
		m_chameleon = new Player(100, *startingRoom);		
	}
	catch(std::bad_alloc&)
	{
		std::cout << "Could not allocate memory to initalize the player\n";
	}
	Room& currentRoom = m_chameleon->GetPlayerLocation();
	// print welcome information
	PrintWelcome();
	// print current room info
	currentRoom.PrintRoomInfo();
	// store commands in local map
	argument_mapping commands = GetGameCommands();
	// main game loop
	do
	{
		std::string input = GetUserInput();
		interpret_command(commands, input);
		// string for if player wants to continue
		std::string ans;
		do
		{
			std::cout << "Keep playing? y/n\n";
			std::getline(std::cin, ans);
			ans = gh.ToLower(ans);
		}while(ans != "n" && ans != "y");
		if(ans == "n")
		{
			m_keepPlaying = false;
		}
	}while(m_keepPlaying);
	// clean up the memory
	CleanUp();
}

void Game::CreateRooms(World& w)
{
	Room basement("basement");
	Room hallway("hallway");
	Room lounge("lounge");
	Room lobby("lobby");
	Room office("office");
	Room security("security center");

	basement.SetDescription("The basement is quite empty and safe. You hear noise above you.");
	hallway.SetDescription("Like the rest of the building, the hallway has a cold, metallic touch.");
	lounge.SetDescription("In the lounge area, you see a television set and a couple couches.");
	lobby.SetDescription("A big open area, that holds the main entrance doors to the building.");
	office.SetDescription("An office room, documentation of all activities in the city");
	security.SetDescription("One of the many cctv offices and control centres in the building");

	w.push_back(basement);
	w.push_back(hallway);
	w.push_back(lounge);
	w.push_back(lobby);
	w.push_back(office);
	w.push_back(security);
	SetExits(w);
}

void Game::SetExits(World& w)
{
	Room* pBasement = &w[0];
	Room* pHallway = &w[1];
	Room* pLounge = &w[2];
	Room* pLobby = &w[3];
	Room* pOffice = &w[4];
	Room* pSecurity = &w[5];

	pBasement->SetExit("south", pHallway);

	pHallway->SetExit("up", pLounge);
	pHallway->SetExit("north", pHallway);

	pLounge->SetExit("north", pLobby);
	pLounge->SetExit("down", pHallway);

	pLobby->SetExit("west", pOffice);
	pLobby->SetExit("south", pLounge);

	pOffice->SetExit("south", pSecurity);
	pOffice->SetExit("east", pLobby);

	pSecurity->SetExit("north", pOffice);
}

void Game::PrintWelcome()
{
	std::cout << "Welcome to the rpg game called Chameleon!\n" 
		<< "You are a highly trained operative named The Chameleon\n"
		<< "You have snuck into an enemy spire. You are required to \n"
		<< "disable their operational systems\n" 
		<< "and take out their leader.\n\n"
		<< "To get started, and learn the commands, type help\n"
		<< "To move from room to room, use the go command, \n"
		<< "followed by listed exits of your current location.\n"
		<< "You can ofcourse display the current exits, by typing exits.\n\n"
		<< "Be sure to have fun, and when having trouble, type /help\n\n\n";
}

void Game::CleanUp()
{
	delete m_chameleon;
}

Game.h

#ifndef GAME_H
#define GAME_H

#include "stdafx.h"
#include <vector>
#include <string>



class Game
{
public:
	Game()
	{
		m_keepPlaying = true;
	}

	// Command data structure
	struct Command;	

	typedef std::vector<Room> World;
	// type definitions for commands
	typedef std::vector<std::string> arguments;
	typedef void (*action)(const arguments&);
	typedef std::map<std::string, Command> argument_mapping;

	// main function that holds the game loop
	void PlayGame();

	// helper functions

	// Creates all the rooms appropriately 
	void CreateRooms(World& w);

	// Adds all the exits to the rooms
	void SetExits(World& w);	
	
	// prints starting messages for the game
	// gives basic instructions
	void PrintWelcome();
	
	// release the used memory
	void CleanUp();

	// functions used for command functionality
	std::string first_word_of(const std::string& line);
	std::string rest_of(const std::string& line);
	std::vector<std::string> split_into_words(const std::string& str);

	// functions for the different commands
	void Go(const arguments& args);
	void Help(const arguments& args);
	void Quit(const arguments& args);
	void Exits(const arguments& args);
	void Save(const arguments& args);
private:
	Player* m_chameleon;
	bool m_keepPlaying;
};

#endif

Advertisement
The error is that your not declaring the method "split_into_words" as a static function. In order to use methods that pertain to a class you must first make the object.


 Game someGame; someGame.split_into_words; 


If all you want to accomplish is having the functions in a namespace then use a namespace and not a class.

namespace Game{.... stuff from your class here ...}


However I would just keep the class and use it properly, I recommend you read a good book about C++ and Object Oriented Programming.
I didn't go through the entire code, but maybe try:

void operator()(const std::string& command_line,Game& game) {   a(game.split_into_words(command_line));}


It looks like you are trying to call a method of Game without specifying the actual (instantiated) Game object. If split_into_words() was declared static, then you could call Game::split_into_words() instead (hence the 'strange' compiler error?)

Of course, I don't specifically know what you are trying to do, so I may be totally off here (in which case, just ignore me [grin]

edit: ninja'd!
I did think of that, adding a game object to the commands. However, not all of them will need it, and that would be a waste to do it for every one, and I think theres probably a better way around it.

Seoushi, are there any books you'd recommend that cover OO with C++?
I have a hard time recommending a good C++ book as most everything I've seen is C with classes and it's been such a long time since I needed to look for a C++ book. This book seems like your best bet, however I have not read it. It's written by the original author of C++ and is used to teach his university course.
I enjoy reading the books from the game development series by Andre LaMothe. There are a bunch in the series, just look up his name.
Tricks of the 3D Game Programming is a good overview.
Quick, what's wrong with the following code?

x = int - 5;


It's the same thing with classes: they define a data type. To call member functions, you must have an instance (object) of the class for the member to be a member of.

You may have heard of constructors and destructors, BTW. They are used for initialization and cleanup of the instance. You want to use these, and not named functions like "Cleanup". The advantage of the constructors and destructors is that there is no way to forget to call them.

I get the impression from your code that you don't really want to make a class anyway. Use a namespace instead. You can think about trying to make things "object-oriented" later.
My OO definitely needs improvement, and I would really like to get my programming into that mindset. In terms of books, grabbed this one from the back shelf of a computer lab at school. Its pretty massive, has around 1300 pages, and has a couple chapters focused on OO.

Was also thinking of getting this one: C++ Programming Language
About "C++ Programming Language": if you are serious about C++, I think I would recommend this book, at the very least for a solid reference. However, it's not for beginners -- this book covers just about everything about the language (except for the more 'modern' stuff, like template metaprogramming, tr1 and boost). You should already be fairly comfortable with Cpp syntax (including templates) before diving into this one -- some of the code blocks, although short, took me a some time to figure out, since I'm not overly experienced with templates and advanced STL (yet!)

I like the Scott Meyers books, too, but again, I would think they are more for intermediate C++ users than beginners -- but he gives (IMO) good advice here and there about OO (including novel ways to implement OO in C++).

Anyway, just my opinion

This topic is closed to new replies.

Advertisement