Thread: Providing access to member variables between classes

  1. #1
    Registered User Tonto's Avatar
    Join Date
    Jun 2005
    Location
    New York
    Posts
    1,465

    Providing access to member variables between classes

    Okay, so I have this grid contained by a screen class like, and I am trying to design a member function to add, like, 'Thingies' to the grid.

    Code:
    class Screen
    {
    public:
    	void add(const Thingy & t);
    ...
    
    private:
    	bool ** scr;
    	int rows;
    	int cols;
    
    };
    And then a Thingy that has a chain of the coordinates it occupies like this

    Code:
    class Thingy
    {
    ...
    
    protected:
    	std::vector<COORD> v;
    
    ...
    };
    I want to flip on parts of the scr array based on the COORD's in the Thingy. I also want to derive from Thingy and make monsters and players and other wierd sorts of classes. Would it be good to just have accessors that provide access to the vectors size and COORD's at diff. indexes, or would it be better to make it public, or is there a better solution?

  2. #2
    carry on JaWiB's Avatar
    Join Date
    Feb 2003
    Location
    Seattle, WA
    Posts
    1,972
    You could make Thingy a friend of Screen, although I think using friends is usually frowned upon. I would think it would be better just to have accessors to preserve encapsulation, but I'm not a design expert.
    "Think not but that I know these things; or think
    I know them not: not therefore am I short
    Of knowing what I ought."
    -John Milton, Paradise Regained (1671)

    "Work hard and it might happen."
    -XSquared

  3. #3
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    If you don't want any other classes besides derived classes and Screen to have an interface to COORD information in Thingy, I'd make it a friend. Making public interface methods exposes whatever interface you want to give to Screen to all other users of the class. However, if the part of the goal of the Thingy class is to expose that interface, then make the member functions public even if Screen happens to be the only class to use them.

    Another choice is to separate the COORD data into a separate class that knows how to flip on or off parts of the scr array.

  4. #4
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Since it is best not only to design a functional class hierarchy, but also design it so it cannot be misused accidentally or deliberately - friend's come in handy.

    Friend is very good for classes which manage objects and are responsible for object instantiation - such as in the case of singleton classes.

    However friend can be misused just like all of C++ can be misused. I suggest purchasing a book on common design patterns from www.amazon.com.

    It is impossible to explain how and how not to design a class hierarchy in the scope of this thread.

  5. #5
    Registered User Tonto's Avatar
    Join Date
    Jun 2005
    Location
    New York
    Posts
    1,465
    Okay. I am trying out using friend's, but not without some errors and confusion first. Here's how I've tried laying out these classes:

    coord.h
    Code:
    #ifndef __COORD_H__
    #define __COORD_H__
    
    struct Coord
    {
    	Coord(int a, int b) : 
    	  x(a), y(b) { }
    
    	int x, y;
    };
    
    #endif
    And thingy.h
    Code:
    #ifndef __THINGY_H__
    #define __THINGY_H__
    
    
    #include <vector>
    #include "coord.h"
    #include "screen.h"
    
    class Thingy
    {
    	friend void Screen::add(const Thingy & t);
    public:
    	Thingy();
    	virtual ~Thingy();
    protected:
    	std::vector<Coord> v;
    };
    
    
    #endif
    And screen.h
    Code:
    #ifndef __SCREEN_H__
    #define __SCREEN_H__
    
    
    #include "thingy.h"
    #include <windows.h>
    
    
    class Thingy;
    class Screen
    {
    public:
    	Screen(int rows = 10, int cols = 10);
    	~Screen();
    
    	
    	void paint(HWND hwnd);
    	void add(const Thingy & t);
    
    protected:
    private:
    	bool ** scr;
    	int rows;
    	int cols;
    };
    
    #endif
    And finally screen.cpp
    Code:
    #include "screen.h"
    
    //...
    void Screen::add(const Thingy& t)
    {
    	for(std::vector<Coord>::iterator i = v.begin(); i != v.end(); ++i);
    }
    //...

    thingy.h gets an "error C2027: use of undefined type 'Screen'" pointing to the friend declaration. screen.cpp gets errors for v being undeclared. Any way I should rearrange things or declare things?

  6. #6
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446
    For one, screen.h is making a forward declaration of thingy and yet you have the include in place. So, no need for the forward declaration.

    Also, I don't think you need the screen include in thingy. Replace it with a forward declaration of screen.
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  7. #7
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    By the way, names that contain a double underscore or begins with an underscore followed by an uppercase letter are reserved to the implementation for any use. With that in mind, you might want to modify your header guard identifiers.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  8. #8
    Registered User Tonto's Avatar
    Join Date
    Jun 2005
    Location
    New York
    Posts
    1,465
    Same exact errors.

    Code:
    #ifndef i__THINGY_H__i
    #define i__THINGY_H__i
    
    
    #include <vector>
    #include "coord.h"
    
    class Screen;
    class Thingy
    {
    	friend void Screen::add(const Thingy & t);
    public:
    	Thingy();
    	virtual ~Thingy();
    protected:
    	std::vector<Coord> v;
    };
    
    
    #endif
    Code:
    #ifndef i__SCREEN_H__i
    #define i__SCREEN_H__i
    
    
    #include "thingy.h"
    #include <windows.h>
    
    
    class Screen
    {
    public:
    	Screen(int rows = 10, int cols = 10);
    	~Screen();
    
    	
    	void paint(HWND hwnd);
    	void add(const Thingy & t);
    
    protected:
    private:
    	bool ** scr;
    	int rows;
    	int cols;
    };
    
    #endif
    Last edited by Tonto; 06-19-2006 at 12:33 PM.

  9. #9
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446
    Wait. My bad.

    The class granting friendship (thingy) must be defined last. And the friend class (screen) must have access to thingy name.

    So...
    Thingy includes screen.
    Screen forward declares thingy
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  10. #10
    Registered User Tonto's Avatar
    Join Date
    Jun 2005
    Location
    New York
    Posts
    1,465
    I get an "error C2653: 'Screen' : is not a class or namespace name" pointing to the friend declaration line in Thingy when I do that.

  11. #11
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Perhaps something like this:

    screen.h
    Code:
    #ifndef SCREEN_H
    #define SCREEN_H
    
    class Thingy;
    
    class Screen
    {
    public:
    	void add(const Thingy & t);
    };
    
    #endif
    screen.cpp
    Code:
    #include "screen.h"
    #include "thingy.h"
    
    #include <vector>
    
    void Screen::add(const Thingy & t)
    {
    	for (std::vector<int>::const_iterator i = t.v.begin(); i != t.v.end(); ++i);
    }
    thingy.h
    Code:
    #ifndef THINGY_H
    #define THINGY_H
    
    #include <vector>
    #include "screen.h"
    
    class Thingy
    {
    public:
    	friend void Screen::add(const Thingy& t);
    private:
    	std::vector<int> v;
    };
    #endif
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  12. #12
    Registered User Tonto's Avatar
    Join Date
    Jun 2005
    Location
    New York
    Posts
    1,465
    Works perfectly now, thank you kindly

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. OOP Question DB Access Wrapper Classes
    By digioz in forum C# Programming
    Replies: 2
    Last Post: 09-07-2008, 04:30 PM
  2. classes as member variables
    By Stonehambey in forum C++ Programming
    Replies: 13
    Last Post: 08-14-2008, 07:01 PM
  3. derived class can not access base class protected member?
    By George2 in forum C++ Programming
    Replies: 2
    Last Post: 10-21-2007, 06:32 PM
  4. file reading
    By gunghomiller in forum C++ Programming
    Replies: 9
    Last Post: 08-07-2007, 10:55 PM
  5. class member access denied
    By chiqui in forum C++ Programming
    Replies: 2
    Last Post: 05-27-2002, 02:02 PM