accessing private

Started by
16 comments, last by Aldacron 18 years, 11 months ago
Quote:Original post by Drew_Benton
Quote:Original post by C_Programmer0101
Hello guys I am having a problem getting this program to access a file in one of my header files for example:
*** Source Snippet Removed ***
It can not access the name array that is private.
*** Source Snippet Removed ***
My question is in main you notice that roomsArray[currentroom].name;
How can I get roomsArray to access name[32] in the rooms header file?


What you need to do is create a set of accessors for this class, as was mentioned by RDragon1. For example:


::clubs Drew over the head::

Let's stick with some proper design shall we? I.e. putting code where it belongs?

class Room {public:    void display(ostream& where) {      where << "You emerge in the " << name;      where << description;    }};


The idea behind having private variables is that "outside" code is not supposed to be concerned with them. Therefore, operations that make use of that data belong on the "inside" - they describe things that a given object of the class can do. For example, a given room can display itself.
Advertisement
*Throws rotten tomatoes at Zahlman*

Quote:Original post by Zahlman
The idea behind having private variables is that "outside" code is not supposed to be concerned with them.


That's not the 'idea' behind them, though it doesn't hurt to use them that way. Private variables are useful to maintain data integrity and to provide a consistent inrerface to the outside, no matter what happens inside with the implementation. If your private data needs to be available outside, then accessors (or getters) are the appropriate solution.

Additionally, sometimes it's best to use such accessors internally as well, rather than manipulating the variables directly. Maybe you want to change the variable name later (though search and replace handles that easily enough), or add some additional code to run everytime a particular variable is accessed. Implementation hiding works just as well internally as it does externally.

Quote:
For example, a given room can display itself.


What if you want to display a room in many different ways? Would you rewrite the room class multiple times? I sure hope not. It's much cleaner to have something like a RoomDisplay interface. Implementations would then pull the data from Room objects via accessors to display in their own way.
Quote:Original post by Aldacron
*Throws rotten tomatoes at Zahlman*

Quote:Original post by Zahlman
The idea behind having private variables is that "outside" code is not supposed to be concerned with them.


That's not the 'idea' behind them, though it doesn't hurt to use them that way. Private variables are useful to maintain data integrity and to provide a consistent inrerface to the outside, no matter what happens inside with the implementation. If your private data needs to be available outside, then accessors (or getters) are the appropriate solution.


The private variables DO NOT provide the interface to the outside - they are often concerned with the implementation details within the class TO an interface. This is a distinction (and a relatively important one). You can have an interface that is basically accessors to these variables but if at some later point you change the variables, this does not change the interface.
Quote:
The idea behind having private variables is that "outside" code is not supposed to be concerned with them. Therefore, operations that make use of that data belong on the "inside" - they describe things that a given object of the class can do. For example, a given room can display itself.

Quote:
What if you want to display a room in many different ways? Would you rewrite the room class multiple times? I sure hope not. It's much cleaner to have something like a RoomDisplay interface. Implementations would then pull the data from Room objects via accessors to display in their own way.

You're both right, in a way. An object's methods should be a good representation of the object itself, but at the same time, object's should only expose the bare minimum amount of methods that make sense; in this case, the Room object would consist of a constructor accepting the name and description, and two get methods--one for the name, and one for the description. The displaying capability would be lifted out to another class, just as Aldacron suggested.
What am I doing wrong:

#ifndef BATTLE_H#define BATTLE_Hclass battle{public:battle();void initializeBattle();};#endif


#ifndef EQUIPMENT_H#define EQUIPMENT_Hclass equipment{      public:             equipment();             void initializeEquipment();             void giveItem();             char equipmentArray[0];           private:                          char type[16];              char name[32];              int bonus;              };              #endif


#ifndef MONSTER_H#define MONSTER_Hclass monster{      public:             monster();             void initializeMonsters();            private:              int strength;              int dextarity;              int hp;              char name[32];              };              #endif          


#ifndef PLAYER_H#define PLAYER_Hclass player{      public:             player();             void initializePlayer();                                     private:              int hp;              int strength;              int dextarity;              int exp;              char name[32];              int armor;              int sheild;              };              #endif


#ifndef ROOMS_H#define ROOMS_Hclass rooms{      public:             rooms();             void initializeRooms();                                private:             char name[32];             char description[500];                                         int north;              int south;              int east;              int west;              };              #endif


#include <cstdlib>#include <iostream>#include <ctime>#include <cctype>#include "battle.h"battle::battle(){//nothing to initialize}void battle::initializeBattle(){	int attackstrength = 0;	int defencestrength = 0;    int monsterattack = 0;	int monsterdefence = 0;	int randommonster = 0;	srand(static_cast<unsigned>(time(0)));	randommonster = (rand()%6 + 1);	cout << "A " << monsterArray[randommonster].name << "Appears. \n" << endl;	cout << monsterArray[randommonster].name << "has" << monsterArray[randommonster].strength << "strength" << endl		 << monsterArray[randommonster].name << "has" << monsterArray[randommonster].dexterity << "dexterity" << endl		 << monsterArray[randommonster].name << "has" << monsterArray[randommonster].hp << "HP \n" << endl;	do	{	  attackstrength = (character.strength + character.weapon) * (rand()%10 + 1);	  cout << character.name << " deals " << attackstrength << " damage" << endl;	  monsterdefence = (monsterArray[randommonster].dexterity * (rand()%5+1));	  cout << monsterArray[randommonster].name << " defends " << monsterdefence << " Hit Points" << endl;	  if (attackstrength > monsterdefence)		 {			 monsterArray[randommonster].hp = monsterArray[randommonster].hp - (attackstrength - monsterdefence);			 cout << "The monster now has " << monsterArray[randommonster].hp << "Hit points!" << endl;		 }	  else		 {			 monsterArray[randommonster].hp = monsterArray[randommonster].hp;			 cout << "You have failed to harm the monster!\n" << endl;		 }	  monsterattack = (monsterArray[randommonster].strength * (rand()%5+1));	  cout << monsterArray[randommonster].name << " does " << monsterattack << "damage!" << endl;   defencestrength = (character.dexterity + character.shield) * (rand()%5 + 1);	  cout << character.name << " defends " << defencestrength << "Hit Points!" << endl;	  if (monsterattack > defencestrength)		 {			 character.hp = character.hp - (monsterattack - defencestrength);			 cout << "You have been hit! You now have " << character.hp << "Hit Points! \n" << endl;		 }	  else		 {			 character.hp = character.hp;			 cout << "You have defended the monsters attack! \n ...And now have " << character.hp << "Hitpoints! \n" << endl;		 }	}while (monsterArray[randommonster].hp > 0);}


#include <cstdlib>#include <iostream>#include <ctime>#include <cctype>#include "battle.h"battle::battle(){//nothing to initialize}void battle::initializeBattle(){	int attackstrength = 0;	int defencestrength = 0;    int monsterattack = 0;	int monsterdefence = 0;	int randommonster = 0;	srand(static_cast<unsigned>(time(0)));	randommonster = (rand()%6 + 1);	cout << "A " << monsterArray[randommonster].name << "Appears. \n" << endl;	cout << monsterArray[randommonster].name << "has" << monsterArray[randommonster].strength << "strength" << endl		 << monsterArray[randommonster].name << "has" << monsterArray[randommonster].dexterity << "dexterity" << endl		 << monsterArray[randommonster].name << "has" << monsterArray[randommonster].hp << "HP \n" << endl;	do	{	  attackstrength = (character.strength + character.weapon) * (rand()%10 + 1);	  cout << character.name << " deals " << attackstrength << " damage" << endl;	  monsterdefence = (monsterArray[randommonster].dexterity * (rand()%5+1));	  cout << monsterArray[randommonster].name << " defends " << monsterdefence << " Hit Points" << endl;	  if (attackstrength > monsterdefence)		 {			 monsterArray[randommonster].hp = monsterArray[randommonster].hp - (attackstrength - monsterdefence);			 cout << "The monster now has " << monsterArray[randommonster].hp << "Hit points!" << endl;		 }	  else		 {			 monsterArray[randommonster].hp = monsterArray[randommonster].hp;			 cout << "You have failed to harm the monster!\n" << endl;		 }	  monsterattack = (monsterArray[randommonster].strength * (rand()%5+1));	  cout << monsterArray[randommonster].name << " does " << monsterattack << "damage!" << endl;   defencestrength = (character.dexterity + character.shield) * (rand()%5 + 1);	  cout << character.name << " defends " << defencestrength << "Hit Points!" << endl;	  if (monsterattack > defencestrength)		 {			 character.hp = character.hp - (monsterattack - defencestrength);			 cout << "You have been hit! You now have " << character.hp << "Hit Points! \n" << endl;		 }	  else		 {			 character.hp = character.hp;			 cout << "You have defended the monsters attack! \n ...And now have " << character.hp << "Hitpoints! \n" << endl;		 }	}while (monsterArray[randommonster].hp > 0);}


#include <cstdlib>#include <iostream>#include <ctime>#include <cctype>#include "equipment.h"#include "monster.h"#include "player.h"#include "rooms.h"#include "battle.h"using namespace std;void initializeBattle();void giveItem();int randomNumber(int);int main(){    rooms roomsArray[11];equipment equipmentArray[9];player character;equipment e;monster m;player p;rooms r;battle b;e.initializeEquipment();m.initializeMonsters();p.initializePlayer();r.initializeRooms();b.initializeBattle();e.giveItem();    system("PAUSE");    return EXIT_SUCCESS;}


#include <cstdlib>#include <iostream>#include <ctime>#include <cctype>#include "monster.h"monster::monster(){               strength=0;               dextarity=0;               hp=0;               name[32]={0};}void monster::initializeMonsters(){ monsterArray[0].strength = 40; monsterArray[0].dexterity = 10; monsterArray[0].hp = 30; strcpy(monsterArray[0].name, "Orc"); monsterArray[1].strength = 10; monsterArray[1].dexterity = 40; monsterArray[1].hp = 30; strcpy(monsterArray[0].name, "Elven Archer"); monsterArray[2].strength = 20; monsterArray[2].dexterity = 30; monsterArray[2].hp = 30; strcpy(monsterArray[0].name, "Undead Corpse"); monsterArray[3].strength = 30; monsterArray[3].dexterity = 30; monsterArray[3].hp = 20; strcpy(monsterArray[0].name, "Marine");  monsterArray[4].strength = 30; monsterArray[4].dexterity = 30; monsterArray[4].hp = 30; strcpy(monsterArray[0].name, "Elite Marksman"); monsterArray[5].strength = 70; monsterArray[5].dexterity = 50; monsterArray[5].hp = 10; strcpy(monsterArray[5].name, "Hannibal");}


#include <cstdlib>#include <iostream>#include <ctime>#include <cctype>#include "player.h"player::player(){               strength=0;               dextarity=0;               hp=0;               exp=0;               name[32]={0};               armor=0;               sheild=0;}void player::initializePlayer(){     char username[32];		char move;	int currentroom = 0; cout << "What is your name??? \n" << endl; cin >> username;	cout << "------------------------------------------ \n" << endl; strcpy(character.name, username); character.hp = 100; character.armour=0; character.shield=0; character.weapon=0; cout << endl << username << " Please insert your strength. This will determine the ammount of damage you will inflict. 30-40 is a good ammount. However you may make this number ludacrisly high! \n" <<endl;	cin >> character.strength;	cout << "------------------------------------------ \n" << endl;	cout << endl << username << " Please insert your dexterity. This will determine the ammount of damage that you will have inflicted upon you. The more dexterity, the less total damage. 30 - 40 is a good ammount. Once again you can make this ludacrisly high! \n" << endl;	cin >> character.dexterity;	cout << "------------------------------------------ \n" << endl;	cout << "==========================================" << endl; cout << "Brave " << username << " you have just returned from a recent holiday,"   << "only to find that your village has been pillaged and destroyed."   << "Upon returning to your hut you see your father, mother and sister"    << " laying lifeless in pools of their own blood. Without hesitation"   << " you start sprinting towards Sir Lucifer Hannible's castle."    << "The castle rests upon a hill that overlooks your town. "    << "You know that by the end of today you will kill "   << " hannible and his minions and burn his csatle to cinders."   << " It is your duty to yourslef and the many villages that surrround yours to"   << " assasinate this threat. I wish you luck " << username << ". Who am I you ask?"	<< "I am your dead grandfather that died to the merciless hand of Hannible. "		 << "Now go grandson."		 << "At any time (except during battle) you may press 'c' to display your stats!"		 << "Simply use 'e','w','n' or 's' to navigate, where and as appropriate." << endl; cout << "========================================== \n" << endl;}


#include <cstdlib>#include <iostream>#include <ctime>#include <cctype>#include "rooms.h"rooms::rooms(){               name[32]={0};               description[500]={0};               north=0;               south=0;               east=0;               west=0;}void rooms::initializeRooms(){char move;int currentroom = 0; cout << "You emerge in the " <<roomsArray[currentroom].name; cout << roomsArray[currentroom].description;	while (character.hp > 0) {	if (roomsArray[currentroom].north != -1)	{	   cout << "You may move north \n";	}	if (roomsArray[currentroom].south != -1)	{	   cout << "You may move south \n";	}	if (roomsArray[currentroom].east != -1)	{	   cout << "You may move east \n";	}	if (roomsArray[currentroom].west != -1)	{	   cout << "You may move west \n";	}	cout << "please enter your move: " << endl;	cin >> move;	move = toupper(move);	if (move == 'E') currentroom = roomsArray[currentroom].east;	if (move == 'W')	   currentroom = roomsArray[currentroom].west;	if (move == 'N')	   currentroom = roomsArray[currentroom].north;	if (move == 'S')	   currentroom = roomsArray[currentroom].south;   if (move == 'C')	   cout << "You have " << character.hp << " HP." << endl;	   cout << "You have " << character.strength << " strength." << endl;	   cout << "You have " << character.dexterity << " dexterity." << endl;	if (move != 'E' && move != 'W' && move != 'S' && move!= 'N')	cout << "Please insert either 'N', 'E', 'S' or 'W'! " << endl;	cout << "You emerge in the " << roomsArray[currentroom].name << endl;	cout << roomsArray[currentroom].description << endl;	initializeBattle();	giveItem();	}	cout << "You have failed to beat Hannibal and his minions. You have also "		 << "failed to avenge your Grandfather. What where you thinking going "		 << "into the castle so weak (*hint make stats higher)!" << endl;         strcpy(roomsArray[0].description, "This room is extravagant. There are gold chandaliers on the roof, and a table with gold goblets and plates. There are no windows, and a fireplace to the north illuminates the room. There is a door at the eastern side of the room\n"); strcpy(roomsArray[0].name, "Foyer Room\n");	roomsArray[0].north = -1;	roomsArray[0].south = -1;	roomsArray[0].east = 1;	roomsArray[0].west = -1;	strcpy(roomsArray[1].description, "You emerge into a dark hallway with a single torch in the middle. There are no distinguishing features about this room, and there is a door in the eastern side of the room.\n"); strcpy(roomsArray[1].name, "Dark Hallway\n");	roomsArray[1].north = -1;	roomsArray[1].south = -1;	roomsArray[1].east = 2;	roomsArray[1].west = 0;	strcpy(roomsArray[2].description, "There is a massive fountain in the middle of the room. Its water glows some sort of a heavenly radiance. Upon drinking it you feel revitalised and like a new man. Your HP is restored to its maximum level. There are doors on the northern, eastern and southern sides of the room. \n");	strcpy(roomsArray[2].name, "Foutain Room\n");	roomsArray[2].north = 3;	roomsArray[2].south = 4;	roomsArray[2].east = 6;	roomsArray[2].west = 1;	strcpy(roomsArray[3].description, "Upon stumbling onto this room, you are drenched to your knees in water. As well as being wet, it is also dark and has no distincitive features or items. There are door in on the eastern and southern sides of the room.\n");	strcpy(roomsArray[3].name, "Swamp\n");	roomsArray[3].north = -1;	roomsArray[3].south = 2;	roomsArray[3].east = 5;	roomsArray[3].west = -1;	strcpy(roomsArray[4].description, "A bright lantern illuminates this beatiful room. There are exotic flowers on either sides of it and a treasure chest full of dublons in the top right hand corner. There are doors on the eastern, southern and western sides of the room.\n"); strcpy(roomsArray[4].name, "Treasure Room\n");	roomsArray[4].north = 2;	roomsArray[4].south = -1;	roomsArray[4].east = 7;	roomsArray[4].west = -1; strcpy(roomsArray[5].description, "Another lusicious and overdone room. Crystals that are on the ground reflect the portraits on the walls. There are doors on the southern and western sides of this room. \n"); strcpy(roomsArray[5].name, "Counting Room\n");	roomsArray[5].north = -1;	roomsArray[5].south = 6;	roomsArray[5].east = 8;	roomsArray[5].west = 3; strcpy(roomsArray[6].description, "The total opposite of the beatiful fountain room. It reeks of a peculiar smell and is bare with nothing interesting in it. There are doors on every corner of this room. \n"); strcpy(roomsArray[6].name, "Barn \n");	roomsArray[6].north = 5;	roomsArray[6].south = 7;	roomsArray[6].east = 2;	roomsArray[6].west = 9; strcpy(roomsArray[7].description, "This majestic room has treasure scattered everywhere. In the middle is a large four post king sized bed. There are doors on every corner of this room.\n");	strcpy(roomsArray[7].name, "Master Bedroom \n");	roomsArray[7].north = 6;	roomsArray[7].south = -1;	roomsArray[7].east = -1;	roomsArray[7].west = 4;	strcpy(roomsArray[8].description, "This room is the workers quarters. There are many small uncomfortable beds in running on each wall. There are windows on the northern and eastern walls and doors on the southern and western walls. \n");	strcpy(roomsArray[8].name, "Minions Quarters \n");	roomsArray[8].north = -1;	roomsArray[8].south = 9;	roomsArray[8].east = -1;	roomsArray[8].west = 5;	strcpy(roomsArray[9].description, "What on earth is this. Could it be a mirage? You see luchsious palm tree circling a lagoon with many fish and aquatic lifeforms. There are doors the norhtern, eastern and western sides of the room. \n");	strcpy(roomsArray[9].name, "Tropical Lagoon \n");	roomsArray[9].north = 8;	roomsArray[9].south = -1;	roomsArray[9].east = 10;	roomsArray[9].west = 6;	strcpy(roomsArray[10].description, "The time is now. You see Hannible in his throne. Cigar in one hand, the finest wine in the other. With loud profanity you charge to avenge your grandfather! \n");	strcpy(roomsArray[10].name, "Hannibles Smoking and Sitting Room \n");}


I can not figure it out for the life of me :(
Computers are worlds of Exploration?
Quote:Original post by C_Programmer0101
What am I doing wrong:

*** Source Snippet Removed ***

*** Source Snippet Removed ***

*** Source Snippet Removed ***

*** Source Snippet Removed ***

*** Source Snippet Removed ***

*** Source Snippet Removed ***

*** Source Snippet Removed ***

*** Source Snippet Removed ***

*** Source Snippet Removed ***

*** Source Snippet Removed ***

*** Source Snippet Removed ***

I can not figure it out for the life of me :(


What you are doing wrong is writing too much code at a time without making sure that the previous bit works.

As for the class design, I stand by what I said; simple object properties are overused, really. If the room needs to be displayed in several different ways, those can be represented by either several display functions, or by adding (a) parameter(s) to indicate the type of display to do. Note that I already generalized things a little bit by having cout passed in as a parameter. But even if we would prefer to separate the "display a name" and "display a description" concepts later on, the time to provide that access is - later on, when such a need is proven.

Putting the code inside the class here is just plain better encapsulation, and provides a simpler interface. Why care about the fact that a room has a name and a description, when we could instead just care that it is displayable?
Quote:
What you are doing wrong is writing too much code at a time without making sure that the previous bit works.

Agreed.
Quote:
As for the class design, I stand by what I said; simple object properties are overused, really. If the room needs to be displayed in several different ways, those can be represented by either several display functions, or by adding (a) parameter(s) to indicate the type of display to do. Note that I already generalized things a little bit by having cout passed in as a parameter. But even if we would prefer to separate the "display a name" and "display a description" concepts later on, the time to provide that access is - later on, when such a need is proven.

Look into the Model-View-Controller pattern. Stuffing everything into one class is a bad thing (tm), because you end up with a tangled mess of dependencies. A perfect example of this would be an implementation of a Rectangle class:
class Rectangle {private:  int x, y, width, height;public:  ...  void render(Surface& surface) {    // rectangle drawing code  }};

Now, this may work all and well for a game, but what happens when you want to use it in a non-graphical simulation program? Now, you either have to include the dependencies associated with rendering, or you have to rip out parts of the rectangle class and make sure it still works afterwards. This may not seem like a big deal now, but it gets amplified when you start adding other non-essential routines to the class, such as update methods and collision routines.
Quote:Original post by Zahlman
Putting the code inside the class here is just plain better encapsulation, and provides a simpler interface. Why care about the fact that a room has a name and a description, when we could instead just care that it is displayable?


There's no 'one size fits all' solution. The point I'm trying to get across is that there is more than one reason to use the 'private' keyword and you come across as saying that it is used for one thing only. The idea that 'private' should only be used for internal variables and that objects should always encapsulate their functionality is short sighted. Sometimes it just isn't feasible.

This topic is closed to new replies.

Advertisement