Thread: Class question

  1. #1
    Registered User
    Join Date
    Oct 2006
    Location
    UK/Norway
    Posts
    485

    Class question

    Hallo,

    I am working with adding geometry to a program I am making, and have some questions about the uses of classes.

    Here is my class(s) so far. The idea is to have on base class that has the information that is common for all the geometry types, and then have subclasses(?) for the things that are different.

    Code:
    class Primitive
    {
          public:
                 Primitive();
                 ~Primitive();
                 
                 void setType(); // ??
                 void getType(); // ??   
                 
                 void setName(std::string n);   
                 std::string getName();
                 
                 void setMaterial(Material m);
                 Material getMaterial();
                 
                 void setPos(Vector3D pos);
                 Vector3D getPos();
                 
          private:
                  //type
                  std::string name;
                  Material material;
                  Vector3D position;
    };
    
    class sphere : public Primitive
    {
          public:
                 void setRadius(float r);
                 float getRadius();
                 float getRadiusSqr();
                 
                 result intersectionTest(Ray r);
                 
          private:
                  float radius;
                  float radiusSqr;
    };
    Is this a good way of doing it?

    Also, for the setType/getType, how would you do them? I want to be able to do something like:
    setType(SPHERE);
    and than it knows that that primitive is a sphere. Should I define SPHERE as 1, BOX as 2 and so on, and do it that way?

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Generally, base class destructors should be declared virtual.

    Also, for the setType/getType, how would you do them? I want to be able to do something like:
    setType(SPHERE);
    and than it knows that that primitive is a sphere. Should I define SPHERE as 1, BOX as 2 and so on, and do it that way?
    A better way is to declare virtual functions in the base class that the Sphere, Box, etc derived classes override to provide specific functionality.
    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

  3. #3
    Registered User
    Join Date
    May 2006
    Posts
    903
    First, I would get rid of those get/set methods. The only occasion where I would use those is if the set/get methods do something else than just assignment. For example, if you had a Window class and changed its size, obviously the setSize() function would have to resize the window. However, if you just want to assign a value to a member or get its value, you can just make the variable public. Second, I wouldn't use a setType() function. Also, you want that Primitive class to be abstract so that it is impossible to instantiate it (create an objet with type Primitive). The type idea is pretty much useless. If Primitive is an abstract class and you have multiple classes derived of it, you can just do the following:

    Code:
    void f(Primitive* p)
    {
      if(dynamic_cast<Derived*>(p) != 0)
      {
        // Do something
      }
    }

  4. #4
    Registered User
    Join Date
    Oct 2006
    Location
    UK/Norway
    Posts
    485
    Sorry to ask more, but I did not really understand what you was saying.
    So fuctions that are common should be decleard one time in the base class a virtual (virtual int a())
    and one time in the subclass(int a())?

    EDIT:
    What i want to be able to do is loop trught all of my primitives and call the intersectionTest() without havint to do a check inside the loop what type of primitive they are.
    Last edited by h3ro; 04-23-2007 at 05:52 AM.

  5. #5
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Not so much "common" as "providing functionality that may be customised in derived classes". Of course, if a member function is virtual in a base class, it is also virtual in a derived class whether or not you explicitly declare it virtual. If Primitive is to be an abstract base class, you may consider making those virtual functions pure virtual.
    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

  6. #6
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    However, intersectionTest sounds like it will eventually become a double-dispatch problem, and that's a wholly different can of worms.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  7. #7
    Registered User
    Join Date
    Oct 2006
    Location
    UK/Norway
    Posts
    485
    Hey,

    I am still working on this, how can I acces the intersectionTest() from a primitive?

    Here is how I try to do it:
    Code:
                    // Find the primitive we are currently testing against
                     Primitive testObject = thisScene.getPrimitive(currentPrimitive);
                     
                     // Check if the ray hits the current object
                     intersectionRes = testObject.intersectionTest(currentRay);
    But it tells me that intersectionTest is not a member of primitive

  8. #8
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    What class is thisScene an instance of, and what exactly does getPrimitive() return? Is intersectionTest() a virtual function declared in Primitive?
    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

  9. #9
    Registered User
    Join Date
    Oct 2006
    Location
    UK/Norway
    Posts
    485
    thisScene is basicly an array of primitives.
    getPrimitive returns a given primitive.


    Code:
    class Primitive
    {
          public:
                 Primitive(std::string n = "DefaultName");
                 ~Primitive();
                 
                 void setType(); // ??
                 void getType(); // ??   
                 
                 void setName(std::string n);   
                 std::string getName();
                 
                 void setMaterial(Material m);
                 Material getMaterial();
                 
                 void setPos(Vector3D pos);
                 Vector3D getPos();
                 
          private:
                  //type
                  std::string name;
                  Material material;
                  Vector3D position;
    };
    
    // The subclass for a sphere
    class Sphere : public Primitive
    {
          public:
                 void setRadius(float r);
                 float getRadius();
                 float getRadiusSqr();
                 
                 result intersectionTest(Ray r);
                 
                 
          private:
                  float radius;
    };

  10. #10
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    thisScene is basicly an array of primitives.
    Basically, perhaps, but in actuality it isnt, from what I see.

    getPrimitive returns a given primitive.
    What is currentPrimitive then? You are not giving enough information. Furthermore, you have not taken any of the advice given in this thread. You might rewrite your classes into something like:
    Code:
    class Primitive
    {
    public:
        virtual ~Primitive() {}
    
        void setMaterial(Material m);
        Material getMaterial();
    
        void setPos(Vector3D pos);
        Vector3D getPos();
    
        virtual result intersectionTest(Ray r) = 0;
    private:
        Material material;
        Vector3D position;
    };
    
    class Sphere : public Primitive
    {
    public:
        void setRadius(float r);
        float getRadius();
        float getRadiusSqr();
    
        virtual result intersectionTest(Ray r);
    private:
        float radius;
    };
    Now, given a Primitive* or Primitive& that points or refers to a Sphere (or any object of a derived class of Primitive), you can call it's intersectionTest() function through that pointer or reference.
    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

  11. #11
    Registered User
    Join Date
    Oct 2006
    Location
    UK/Norway
    Posts
    485
    What is currentPrimitive then? You are not giving enough information.
    Sorry, here is how it is done:
    First I have a class that holds all the information about the primitives I have
    Code:
    // This is the class that holds the scene we are rendering. It has all the 
    // object created stored inside 
    class Scene
    {
          public:
                 Scene(){};
                 ~Scene();
                 
                 void createScene();
                 
                 int getNrPrimitives();
                 Primitive getPrimitive(int i);
                 
                 int getNrLights();
                 //Light getLight(int i);
                 
          private:
                  int nrPrimitives;                // nr of primitives in the scene
                  Primitive** primitiveList;  // A list of all the primitives in the scene
                  
                  int nrLights;
                  //Light** lightList;
    };
    and primitive is decleared as above.

    Then I have a loop that loops trough all othe object to find the closest one
    Code:
                // Loop through all the primitives in the scene and return the 
                // the closest one
    // totalPrimitves = the total amount of objects in the scene
                for (int currentPrimitive = 0; currentPrimitive <=totalPrimitves;
                     currentPrimitive++)
                {
                     // Find the primitive we are currently testing against
                     Primitive testObject = thisScene.getPrimitive(currentPrimitive);
                     
                     // Check if the ray hits the current object
                     intersectionRes = testObject.intersectionTest(currentRay);
                 }
    Furthermore, you have not taken any of the advice given in this thread
    I know, as I do not fully understand what you tell me to do. I am trying to ask for more information, aswell as reading online.

    I tryed to do the changes you wrote but I get this erro:
    invalid return type for member function `Primitive Scene::getPrimitive(int)'
    because the following virtual functions are abstract:

    Thanks for all your help so far

  12. #12
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    I know, as I do not fully understand what you tell me to do. I am trying to ask for more information, aswell as reading online.
    Ah, okay. You may want to read up on virtual functions and abstract base classes.

    I tryed to do the changes you wrote but I get this erro:
    invalid return type for member function `Primitive Scene::getPrimitive(int)'
    because the following virtual functions are abstract:
    Instead of returning a Primitive (by value), you should return by pointer or by reference. Dynamic binding (i.e., polymorphism that comes from the use of a virtual function) works via pointers and references.
    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

  13. #13
    Registered User
    Join Date
    Oct 2006
    Location
    UK/Norway
    Posts
    485
    Thanks for the links. Accually the whole page was kind of nice[bookmarked].

    I am still working on this, but I think I have made some progress at least.
    Now I dont get any erros when compiling the class, but I do when I try to acces members of the sphere class.

    Here is what I have for my classes
    Code:
    class Primitive
    {
          public:
                 Primitive(std::string n = "DefaultName");
                 //~Primitive();
                 
                 //void setType(); // ??
                 //void getType(); // ??   
                 
                 void setName(std::string n);   
                 virtual std::string getName();
                 
                 void setMaterial(Material m);
                 virtual Material* getMaterial();
                 
                 void setPos(Vector3D pos);
                 virtual Vector3D getPos();
                 
                 virtual result intersectionTest(Ray r) = 0;
                 
          private:
                  //type
                  std::string name;
                  Material material;
                  Vector3D position;
    };
    
    // The subclass for a sphere
    class Sphere : public Primitive
    {
          public:
                 void setRadius(float r);
                 float getRadius();
                 float getRadiusSqr();
                 
                 result intersectionTest(Ray r); 
          private:
                  float radius;
    };
    And here I try to use it:
    Code:
    // Create a container for all the objects in the scene
         primitiveList = new Primitive*[100];
         
         // Add some object to the scene
         // ----------------------------------------
         
            // A small blue sphere at the scene of the screen
            primitiveList[0] = new Sphere;
            primitiveList[0]->setName("SmallBlueSphere");
            primitiveList[0]->setPos(Vector3D(0,-50,0));
            primitiveList[0]->setRadius(20);
            primitiveList[0]->setMaterial(Material(0,0,255,0)); // Blue with 0 diffuse
            
            primitiveList[1] = new Sphere;
            primitiveList[1]->setName("BigRedSphere");
            primitiveList[1]->setPos(Vector3D(0,50,0));
            primitiveList[1]->setRadius(50);
            primitiveList[1]->setMaterial(Material(255,0,0,0));
         
         // -----------------------------------------
         // Done with the scene
    The error I get is:
    'class Primitive' has no member named 'setRadius'

    Not sure why this happens. I can acces all the functions in the Primitive class, but not in the SPhere class. This would have made sense to me if I had done new Primitive insted of new Sphere.

    So, again I need a helping hand...

    Thanks for you time

  14. #14
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    primitiveList[0] is a Primitive*. As such, any member function of Primitive can be called from it. Sphere is-a Primitive, so whatever member functions Sphere inherits from Primitive can be called via primitiveList[0]. However, setRadius() is a member function first declared in Sphere, and of course Primitive knows nothing about it.

    In this case, you know that primitiveList[0] points to a Sphere object, so you can safely cast it to Sphere*. In particular, you would use dynamic_cast:
    Code:
    Sphere* sphere = dynamic_cast<Sphere*>(primitiveList[0]);
    sphere->setRadius(20);
    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

  15. #15
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Avoid dynamic_cast if you can. In this case, a far better solution is to pass all these parameters like radius, position and whatever to the constructor.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. matrix class
    By shuo in forum C++ Programming
    Replies: 2
    Last Post: 07-13-2007, 01:03 AM
  2. Replies: 8
    Last Post: 10-02-2005, 12:27 AM
  3. Dikumud
    By maxorator in forum C++ Programming
    Replies: 1
    Last Post: 10-01-2005, 06:39 AM
  4. question about DLL's and class functions
    By btq in forum Windows Programming
    Replies: 2
    Last Post: 02-25-2003, 06:08 AM
  5. gcc problem
    By bjdea1 in forum Linux Programming
    Replies: 13
    Last Post: 04-29-2002, 06:51 PM