structs inside classes

This is a discussion on structs inside classes within the C++ Programming forums, part of the General Programming Boards category; Hi, im building an implementation of the A* path finding algrithm, and i have a class which is basically an ...

  1. #1
    Registered User
    Join Date
    Jul 2006
    Posts
    63

    structs inside classes

    Hi, im building an implementation of the A* path finding algrithm, and i have a class which is basically an interface for a linked list

    Code:
    #include <cstdlib>
    #include <iostream>
    
    using namespace std;
    
    
    // these are used to create linked lists of open points availible for testing
    struct point {
        int x;
        int y;
        int value;
        point *next;
    };
    
    class linkedPointList
    {
    private:    
        point *start;
        point *end;  
        point *cur;
        int length;
        
    public:
           
        void appendPoint(int x,int y)
        {
            end->next = new point;
            end = end->next;
            end->x = x;
            end->y = y;
            end->value = 0;
            end->next = 0;
            printf("&#37;d\n",end->x);
            length++;
        } 
        
        point * getPoint(int pNum)
        {
            cur = start;
            for(int i = 0; i <= pNum; i++)
            {
                cur = cur->next;
            }
            return cur;
        }
             
        linkedPointList()
        {
            start = new point;
            start->next = 0;
            cur = start;
            end = start;
            length = 0;
        }      
    };
    
    
    int main(int argc, char *argv[])
    {
        linkedPointList test;
        test.appendPoint(1,2);
        test.appendPoint(3,4);
        point *testPoint;
        testPoint = test.getPoint(0);
        printf("%d\n",testPoint->x);
        system("PAUSE");
        return EXIT_SUCCESS;
    }
    now this is my first ever attempt at programming c++ and my first ever class, but it would seem logical that struct Point should be inside the linkedPointList class, however then if i want to use the getPoint function outside of that class, struct point isnt defined and it wont work. Is there a way around this, and if there isnt what would be common practice when a situation like this occurs. Should i make separate functions for getx, gety, get value, or should i return it as an array?

  2. #2
    Registered User
    Join Date
    May 2007
    Posts
    88
    > but it would seem logical that struct Point should be inside the linkedPointList class,

    It would?

    I am of the opinion that there is absolutely no reason to nest structures inside of classes.

    EDIT: Also, is there any reason in particular why you're creating your own linked list? Are std:list<>'s not good enough?

  3. #3
    Massively Single Player AverageSoftware's Avatar
    Join Date
    May 2007
    Location
    Buffalo, NY
    Posts
    141
    If point is a member of the class, you need to refer to it as linkedPointList::point outside of the class.

    It would?

    I am of the opinion that there is absolutely no reason to nest structures inside of classes.
    If a struct or class only makes sense in the context of another, it makes all the sense in the world to make it nested.
    Last edited by AverageSoftware; 06-16-2007 at 08:17 PM.
    There is no greater sign that a computing technology is worthless than the association of the word "solution" with it.

  4. #4
    Registered User
    Join Date
    May 2007
    Posts
    88
    > If a struct or class only makes sense in the context of another, it makes all the sense in the > world to make it nested.

    Maybe you could give me an example of one such relationship?

  5. #5
    Registered User
    Join Date
    Jan 2005
    Posts
    7,325
    Assume you have a situation where you only need an Address when working with objects of your Person class. You have a class or struct that combines the properties of the Address. Nest this inside Person to indicate that it only makes sense to be used with Person.

    Putting it parallel to Person just pollutes that namespace and doesn't make it as clear that they are so tightly related.

  6. #6
    Massively Single Player AverageSoftware's Avatar
    Join Date
    May 2007
    Location
    Buffalo, NY
    Posts
    141
    Quote Originally Posted by UMR_Student View Post
    > If a struct or class only makes sense in the context of another, it makes all the sense in the > world to make it nested.

    Maybe you could give me an example of one such relationship?
    Certainly.

    The nodes of a linked list are an excellent example. There are purely an implementation detail, and should be a private member of a linked list class. Users of the linked list class have no business even knowing that the node data type exists.

    Specialized exception classes are another good one. If I have a class that represents a network socket, for example, the exceptions that it throws only make sense as members of that object.

    Here is an actual class I use for my game programming that uses both of these:

    Code:
    class SoundWrapper
    {
    public:
        class OpenALInitializeException : public ASException
        {
        public:
            OpenALInitializeException(std::string Msg, void *Thrwr, std::string Methd);
        };
    		
        class OpenALShutdownException : public ASException
        {
        public:
            OpenALShutdownException(std::string Msg, void *Thrwr, std::string Methd);
        };
    		
        SoundWrapper();
        ~SoundWrapper();
        int LoadOggVorbis(std::string Filename) throw (FileNotFound);
        void LoadOggVorbisStream(std::string Filename) throw (FileNotFound);
        void PlaySound(int Target) const;
        void PlayStream() const;
        void PauseStream() const;
        void RewindStream() const;
        void ProcessStream() const;
        void Enable();
        void Disable();
        void ToggleEnabled();
        void ClearSounds();
    		
        static void Initialize() throw (OpenALInitializeException);
        static void Shutdown() throw (OpenALShutdownException);
    		
    private:
        struct Sound
        {
            ~Sound();
    			
            ALuint Buffer;
    	 ALuint Source;
        };
    		
        struct AudioStream
        {
            ~AudioStream();
    			
            ALuint Buffers[2];
    	 ALuint Source;
    	 FILE *StreamFile;
    	 OggVorbis_File FileHandle;
    	 ALenum Format;
    	 ALsizei Frequency;
    	 double LoopPoint;
        };
    		
        void FillBuffer(ALuint ALBuffer) const;
    		
        bool Enabled;
        int SoundCount;
        std::vector<Sound*> SoundList;
        AudioStream *Stream;
    		
        static ALCdevice *SoundDevice;
        static ALCcontext *SoundContext;
        static int Endianness;
    };
    Last edited by AverageSoftware; 06-16-2007 at 08:34 PM.
    There is no greater sign that a computing technology is worthless than the association of the word "solution" with it.

  7. #7
    Registered User
    Join Date
    May 2007
    Posts
    88
    > The nodes of a linked list are an excellent example.

    They're a viable one. I, however, would rather not abstract them, especially if the node type could be useful in other contexts (maybe a similar container uses a node that is a close derivative). Yes, they are an "implementation detail", but, assuming that they function correctly on their own (which all objects should, regardless of the context), it isn't really necessary to abstract them, and it could end up just being a pain in the butt when you extend your program.

    > If I have a class that represents a network socket, for example, the exceptions that it throws only make sense as members of that object.

    Again, I see your point. I simply don't agree philosophically. In my book, sockets are sockets, and exceptions are exceptions. They both make sense on their own.

    >Assume you have a situation where you only need an Address when working with objects of your Person class. You have a class or struct that combines the properties of the Address

    What if you later extend your program with a class called Company? Won't it want to make use of Address? IMHO, the only way you could "pollute" a namespace is with broken, useless, or undocumented objects.


    My main point here is that all data types/objects inherently make sense in all contexts and should function correctly on their own, so there is no need for abstraction. I'm not trying to argue with you guys, though, you make very good points. I am just playing the devil's advocate (as I often do).

  8. #8
    Registered User
    Join Date
    Jul 2006
    Posts
    63
    Sweet, that actually looks.... organized. Hahahaha, C was a mess compared to this. Anyway

    EDIT: Also, is there any reason in particular why you're creating your own linked list? Are std:list<>'s not good enough?
    I wish id known that, lol.

  9. #9
    Registered User
    Join Date
    Jan 2005
    Posts
    7,325
    >> IMHO, the only way you could "pollute" a namespace is with broken, useless, or undocumented objects.

    Perhaps I'm coming at this from a practical point of view after certain possibly dubious design decisions have already been made. Right now in my work I have nested structs inside a larger class that currently have no use whatsoever other than with that class. Primarily the point of these structs is to bundle data together so that it is easier to pass around. The data has logical groupings and so I grouped it.

    Theoretically, these structs could be useful at some point in the future outside this class. However, the likelihood of that is small. If I multiply the cost of moving these structs outside of the class so they can be used elsewhere by the likelihood that it will happen, I get a smaller "headache value" than what I would get from adding these structs to the same namespace as the outer class.

    Besides the fact that it would add to an unfortunately huge amount of classes already in this particular project, it would also require me to make sure the names are unique (they are currently brief and clear). I could put them in their own namespace, but that's essentially what I'm doing by placing them inside the class.

    Anyway, those are my reasons for doing it my particular case. That doesn't mean that it's good practice, but it seems like the right choice to me.

  10. #10
    Registered User
    Join Date
    May 2007
    Posts
    88
    Besides the fact that it would add to an unfortunately huge amount of classes already in this particular project, it would also require me to make sure the names are unique (they are currently brief and clear). I could put them in their own namespace, but that's essentially what I'm doing by placing them inside the class.
    Sounds like you're having a blast at work

    Yeah, and I completely understand your point of view there. It's just a matter of personal preference.

    Primarily the point of these structs is to bundle data together so that it is easier to pass around.
    Maybe I'm missing something, but I'm a little curious as to what passing you could possibly be doing between two methods of the same class?

  11. #11
    Registered User
    Join Date
    Jan 2005
    Posts
    7,325
    The structs are public, so other classes use instances of them when working with the containing class.

    Also, imagine this code (but ignore its simplicity):
    Code:
    class Example
    {
    public:
      struct Data
      {
        std::string name;
        std::string value;
      };
      struct Separators
      {
        std::string middle;
        std::string end;
      };
    
      void OutputData(bool bMaleNotFemale) const;
    
    private:
      Data north_data;
      Data south_data;
      Data east_data;
      Data west_data;
    
      Separators male_sep;
      Separators female_sep;
    };
    
    void Example::OutputData(bool bMaleNotFemale) const
    {
      if (bMaleNotFemale)
      {
        std::cout << north_data.name << male_sep.middle;
        std::cout << north_data.value << male_sep.end;
    
        std::cout << south_data.name << male_sep.middle;
        std::cout << south_data.value << male_sep.end;
    
        std::cout << east_data.name << male_sep.middle;
        std::cout << east_data.value << male_sep.end;
    
        std::cout << west_data.name << male_sep.middle;
        std::cout << west_data.value << male_sep.end;
      }
      else
      {
        std::cout << north_data.name << female_sep.middle;
        std::cout << north_data.value << female_sep.end;
    
        std::cout << south_data.name << female_sep.middle;
        std::cout << south_data.value << female_sep.end;
    
        std::cout << east_data.name << female_sep.middle;
        std::cout << east_data.value << female_sep.end;
    
        std::cout << west_data.name << female_sep.middle;
        std::cout << west_data.value << female_sep.end;
      }
    }
    Now, obviously, that's pretty lame code duplication, right? What if I did this instead:
    Code:
    class Example
    {
    public:
      struct Data
      {
        std::string name;
        std::string value;
      };
      struct Separators
      {
        std::string middle;
        std::string end;
      };
    
      void OutputData(bool bMaleNotFemale) const;
    
    private:
      void OutputData(const Data& data, const Separators& sep) const;
    
      Data north_data;
      Data south_data;
      Data east_data;
      Data west_data;
    
      Separators male_sep;
      Separators female_sep;
    };
    
    void Example::OutputData(bool bMaleNotFemale) const
    {
      const Separators& sep = bMaleNotFemale ? male_sep : female_sep;
    
      OutputData(north_data, sep);
      OutputData(south_data, sep);
      OutputData(east_data, sep);
      OutputData(west_data, sep);
    }
    
    void Example::OutputData(const Data& data, const Separators& sep) const
    {
      std::cout << data.name << sep.middle;
      std::cout << data.value << sep.end;
    }
    Voila!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. allocatable arrays in CLASSes and STRUCTS
    By simone.marras in forum C++ Programming
    Replies: 4
    Last Post: 03-14-2009, 10:50 AM
  2. Class files including other classes
    By combatdave in forum C++ Programming
    Replies: 7
    Last Post: 11-03-2006, 11:37 PM
  3. C++ Classes: Use, Misuse...Confusion.
    By Snorpy_Py in forum C++ Programming
    Replies: 4
    Last Post: 10-23-2006, 01:46 AM
  4. alignment (classes, structs, members)
    By Raven Arkadon in forum C++ Programming
    Replies: 5
    Last Post: 04-07-2006, 06:51 AM
  5. Structs in classes
    By Unregistered in forum C++ Programming
    Replies: 3
    Last Post: 06-06-2002, 11:54 AM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21