friend class

Started by
16 comments, last by icecubeflower 15 years ago
Hey I have a very large class called Gizmo. Now I have a very small class called Bomb. The Bomb class must be defined first because several of the Gizmo functions return pointers to Bombs and manipulate member variables of Bombs. Now suppose I don't ever want anyone to be able to manipulate the member variables of Bombs except for Gizmos? Like if a Gizmo sets the variables a certain way and returns a pointer to a Bomb, whoever recieves that pointer, I want them unable to change the data in the Bomb, I only want them to be able to read it. Well, I can make the Bomb variables private and add functions to return the variables, so now everyone can read the variables but no one can write to them. At first I thought I could make the Gizmo functions that need to write to Bomb variables friends of the Bomb class. But that doesn't work because Bomb has to be declared first. And to declare Gizmo functions friends of Bomb then Gizmo would have to be declared first. There must be a way to do what I want to do. But I don't know what it is. For now everything in Bomb is public.
Advertisement
You can use a forward declaration when you specify a friend class in C++.
It doesn't work.
/*************************************************************************** *   Copyright (C) 2007 by icecubeflower   * *   icecubeflower@yahoo.com   * *                                                                         * *   This program is free software; you can redistribute it and/or modify  * *   it under the terms of the GNU General Public License as published by  * *   the Free Software Foundation; either version 2 of the License, or     * *   (at your option) any later version.                                   * *                                                                         * *   This program is distributed in the hope that it will be useful,       * *   but WITHOUT ANY WARRANTY; without even the implied warranty of        * *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         * *   GNU General Public License for more details.                          * *                                                                         * *   You should have received a copy of the GNU General Public License     * *   along with this program; if not, write to the                         * *   Free Software Foundation, Inc.,                                       * *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             * ***************************************************************************///Gizmo.h//defined it TWO files://Gizmo.cpp//Gizmoswitch.cpp#ifndef GIZMO#define GIZMO#include <fstream>#include "TexBox.h"#include "soundmaster.h"#include "icegrid.h"#include "icedistance.h"#include "switchmaster.h"using namespace std;struct Gizmo;struct Bomb{   int GetDirection();   int GetForce();   friend bool Gizmo::Hitcheck(Bomb *kaboom);private:   float fhor;   float fvert;   float fsize;   //0=player's team   //1=bad guy   //int iteam;   int idirection;   int iforce;};//considered making a GizStatBox structure/linked list that would store variables like base fspeed,//idewey, texbox and just give//Gizmos a pointer to it so only one GizStatBox node for all 100 rats or whatever.  But for now//every rat has own set of variables,//the memory used is insiginificant compared to one map .png image so to hell with it for nowstruct Gizmo{   //in Gizmo.cpp   Gizmo();   ~Gizmo();   //void Gizspawn(ImageVault *imagebox);  //obsolete?  maybe it goes with the editor, we'll see   bool Gizgen(string strgiz, float spawnhor, float spawnvert, ImageVault *imagebox);//   void Gizwrite();//   string texnamegrab(int inum);//   string texnamegrab2(int inum);   Iceblock Gizmove(int idirection, Uint32 history, Icematrix &mapgrid);   Iceblock Gizrun(int idirection, Uint32 history, Icematrix &mapgrid);   bool Hitcheck(Bomb *kaboom);   Gizmo* Hurt(float fpain,ImageVault *imagebox, AudioBox *boombox, float force, int idirection);   void Apocalypse();   void Gizface(int idirection);   Bomb* Attack(AudioBox *boombox);   void SubAttack(Bomb *kaboom, AudioBox *boombox);   GLuint GetPic();   GLuint GetPic(int inum);   int GetType();   void Grow();   void Shrink();   void Teleport(float x, float y, int idirection);   float GetHor();   float GetVert();   bool GetHurt();   float GetSize();   float GetSpin();   float GetHealth();   int GetState();//in Gizmoswitch.cpp  (this is the file you update if you add new Gizmo types)   Gizmo* gizupdate(Gizmo *enemy, int itrick, Icematrix &mapgrid, ImageVault *picbox,                    AudioBox *boombox, Uint32 history);private://in Gizmo.cpp          //only used by Gizmove I think   Iceblock Gizsubmove(int idirection, float fmove, Icematrix &mapgrid);   void SlamSet(int idirection, float force);   Iceblock Gizslam(Uint32 history, Icematrix &mapgrid);   void Gizcalm(Icematrix &mapgrid, Uint32 history);  //called by gizupdate()   void Die(AudioBox *boombox);   bool Hitcheck(Gizmo *killer);//in Gizmoswitch.cpp   void Switcher(int inum);   Iceblock MoveAI(Iceblock icearray[], int ilen);   string name;          //name of the gizmo file   float fhor;   float fvert;   float fspeed;   float basespeed;   float fsize;          //radius in pixels (units)   //float basesize;       //not actually using this yet   int itype;            //type for AI and stuff//   Iceint spawntype;   //probably only used in the editor, game engine probably stores this for no reason   int iturn;            //used for AI, records how much time you want to pass before new command is issued   int iorder;           //see the AI code   float fspin;          //for windmills and stuff   float fhitpoints;   int ipics;            //# of Gizmo pics   int idewey[6];        //see gizmoswitch.cpp   int imax;   GLuint iauto;            //the image we're on   int itimer;           //strictly used to time bhurt   float slamdistance;   float fupdate;        //fupdate generally stores how many pixels Gizmo moved since last pic change and stuff//could get rid of fupdate, fmoment, fpix, fspin, fspeed and make switches for itype, save memory or use//GixStatBox but seems like overkill for now   float fpix;           //tied to fupdate, the number of pixels you want this gizmo to move before you change sprites   float fmoment;        //similar to fpix, time between attack frames   int igizstate;        //see manual if i ever wrote it   bool bhurt;           //is Gizmo invincible?   TexBox giztex;};#endif


It says:
cd '/home/icecube/project5/debug' && WANT_AUTOCONF_2_5="1" WANT_AUTOMAKE_1_6="1" gmake gmake all-recursiveMaking all in srcg++ -DHAVE_CONFIG_H -I. -I/home/icecube/project5/src -I.. -I/usr/include/SDL-D_GNU_SOURCE=1 -D_REENTRANT -O0 -g3 -MT Gizbox.o -MD -MP -MF .deps/Gizbox.Tpo c -o Gizbox.o /home/icecube/project5/src/Gizbox.cppIn file included from /home/icecube/project5/src/Gizbox.h:34,from /home/icecube/project5/src/Gizbox.cpp:21:/home/icecube/project5/src/Gizmo.h:44: error: invalid use of incomplete type 'struct Gizmo'/home/icecube/project5/src/Gizmo.h:38: error: forward declaration of 'struct Gizmo'gmake[2]: *** [Gizbox.o] Error 1gmake[1]: *** [all-recursive] Error 1gmake: *** [all] Error 2*** Exited with status: 2 ***
I said friend class.
Oh. I read this at
http://www.cplusplus.com/doc/tutorial/classes/

"The concepts of class and data structure are so similar that both keywords (struct and class) can be used in C++ to declare classes (i.e. structs can also have function members in C++, not only data members). The only difference between both is that members of classes declared with the keyword struct have public access by default, while members of classes declared with the keyword class have private access. For all other purposes both keywords are equivalent."

I guess when they said "the ONLY difference between both" and "For ALL other purposes both keywords are equivalent" they were exaggerating a little bit, huh?
No, what I meant is that you can friend a class (or a struct) with just a forward declaration. You can't friend a member function of a class (or a struct) with just a forward declaration for the class (or struct).
If I'm not mistaken you can't make methods friends, and even if you could, at this point the only thing that is known about Gizmo is that there exists something by that name.

Of course, why use the struct keyword in an unorthodox manner? :)

[edit]
Quote:
Hey I have a very large class called Gizmo. Now I have a very small class called Bomb. The Bomb class must be defined first because several of the Gizmo functions return pointers to Bombs and manipulate member variables of Bombs.


This is not really a reason why Bomb must be declared earlier. You could forward declare Bomb and separate the declaration and implementation of Gizmo. (A pretty usual procedure.)
Oh. When I read about friendship it was making functions friends but it didn't say how to make a method in a structure a friend. So you guys are telling me I just make the entire structure a friend? That's... what I wanted to do anyway. Cool, I'll try that.

I don't know what you mean, separating the declaration and implementation of Gizmo, visitor. I have the prototype in a .h file and the rest in a .cpp file.
Yeah that worked great. Just friend the class. (struct)
Quote:
I have the prototype in a .h file and the rest in a .cpp file.


Then you already have them separated. Now forward declare Bomb in the header and include the respective header in the cpp file. The point is that the header of Gizmo is not accessing anything in Bomb and doesn't need to know more than it exists.

This tends to reduce dependencies between headers (if you change the header of Bomb, files including Gizmo but not Bomb won't need to be recompiled because the header of Gizmo hasn't changed as it doesn't depend on the header of Bomb) and is a good thing.

This topic is closed to new replies.

Advertisement