How to pass objects to constructor?

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • Gangreen
    New Member
    • Feb 2008
    • 98

    How to pass objects to constructor?

    Hi,

    I am a Java developper, and now I'm trying to learn C++. I'm very new to the programming language. I'm trying to pass objects to a constructor, which I appear to be doing wrong.

    A triangle-object needs to contain references to 3 "Vertex" objects, which are the points of the triangle.

    Triangle.h
    Code:
    #ifndef TRIANGLE_H_
    #define TRIANGLE_H_
    
    #include "Vertex.h"
    
    namespace geometry {
    
    	class Triangle {
    		public:
    			Vertex v1,v2,v3;
    
    			Triangle(Vertex & one, Vertex & two, Vertex & three);
    			virtual ~Triangle();
    		};
    
    	}
    
    #endif /* TRIANGLE_H_ */
    Triangle.cpp
    Code:
    ...
    Triangle::Triangle(Vertex & one, Vertex & two, Vertex & three) {
    		v1 = one;
    		v2 = two;
    		v3 = three;
    	}
    ...
    Vertex.h
    Code:
    #ifndef VERTEX_H_
    #define VERTEX_H_
    
    #include "../algebra/Vector4f.h"
    #include "../algebra/Matrix4f.h"
    using namespace algebra;
    
    namespace geometry {
    
    	class Vertex {
    		public:
    			Vector4f position;
    
    			Vertex(float x, float y, float z);
    
    			float x();
    			float y();
    			float z();
    
    			void transform(Matrix4f& m);
    
    			virtual ~Vertex();
    	};
    
    }
    
    #endif /* VERTEX_H_ */
    The above code generates the error "Triangle.cpp:1 3:63: error: no matching function for call to 'geometry::Vert ex::Vertex()' note: candidates are: geometry::Verte x::Vertex(float , float, float)",

    among others.
    My interpretation is that C++ tries to create the vertex-objects in the call to Triangle::Trian gle(Vertex & one, Vertex & two, Vertex & three) with only this code, whereas I simply want to have one, two and three as placeholders for passed objects when I'm actually using the constructor, like I would have in java.

    As you can see, I am an absolute beginner at C++.
    What am I doing wrong?

    Thanks
  • horace1
    Recognized Expert Top Contributor
    • Nov 2006
    • 1510

    #2
    it is saying that line 2 of triangle.cpp
    Code:
    Triangle::Triangle(Vertex  &one, Vertex  &two, Vertex  &three) {
    requires a default constructor for Vertex, e.g.
    Code:
                Vertex() {};

    Comment

    • Gangreen
      New Member
      • Feb 2008
      • 98

      #3
      I know, but I can't see why. What I'm trying to do there is creating a constructor for a Triangle that takes three Vertex-objects as parameters. I really don't see how having a default constructor for a vertex is relevant.

      I choose to only provide a constructor for a Vertex that takes x,y,z - coordinates. The constructor for a Triangle has no concern in this, it should just accept whatever three vertex-objects I give it when I use it, regardless of the constructor used to create the vertex-objects.

      So why doesn't it just do that? Why do I need a default constructor? I just want to pass objects by reference

      Comment

      • newb16
        Contributor
        • Jul 2008
        • 687

        #4
        use constructor initializers list:
        Triangle::Trian gle(Vertex & one, Vertex & two, Vertex & three) {
        : v1(one)
        , v2(two)
        {
        // the rest of constructor
        ..

        Comment

        • Savage
          Recognized Expert Top Contributor
          • Feb 2007
          • 1759

          #5
          If you write your own constructor the built-in default constructor seizes to exist, so you will have to write it(the default constructor) by yourself.

          Regards,
          Savage

          Comment

          • Gangreen
            New Member
            • Feb 2008
            • 98

            #6
            yes savage, I realise that. I just don't get why C++ forces me to have a default constructor, even when I only wanted parametrized constructors. Anyway, newb16's paramater list did to the trick. No default constructor needed.

            Comment

            • Savage
              Recognized Expert Top Contributor
              • Feb 2007
              • 1759

              #7
              Because vertices contained in Triangle class are real objects and not references, and therefore they need to be constructed. Since initializer list runs "before" constructor, the problem can be solved in this way since the list uses the inbuilt assingment operator .. but what if later on you want to return a Vector by value from some function? Like this:

              Code:
              Vector generateRandomVector()
                      {
                          //generate random vector
                          return  rndVector;
                      }
              , when this function returns it will put its return value on the stack frame by using the default constructor.. only problem is that default constructor has been suppressed by yours assignment constructor and the code wont compile giving you a simmiliar error message as it did before you solved it using initializer's list. ^^

              So if you plan having some function like those above, either write the default constructor, or assign default values to your assignment constructor.

              Regards,
              Savage

              Comment

              • Gangreen
                New Member
                • Feb 2008
                • 98

                #8
                I see, thank you.

                I'm guessing my best option will be to just store references or pointers instead of the objects, since I would like to share vertices between triangles.

                Another question; in the context of randomVertex-function you described:

                Is it possible to return a pointer to an object created in the body of the function like so?
                Code:
                Vertex* generateRandomVertex()
                {
                   //generate random x,y,z-values
                   Vertex v(x,y,z);
                   Vertex* pointer = &v;
                   return  pointer;
                }
                Or would the 'local' object in the body be deconstructed after the return? C++ pointers and memory-management are pretty confusing for me :p

                Comment

                • Savage
                  Recognized Expert Top Contributor
                  • Feb 2007
                  • 1759

                  #9
                  You can, but you need to create the object on the heap and not on the stack like you did here since after function call all local variables of the function get wiped out, so you would return a pointer to some garbage.

                  Write it like this instead:

                  Code:
                  Vertex* generateRandomVertex()
                  {
                     //generate random x,y,z-values
                     Vertex* pointer = new Vertex(x,y,z);
                     return  pointer;
                  }
                  or even better like this:

                  Code:
                  Vertex* generateRandomVertex()
                  {
                     //generate random x,y,z-values
                     return new Vector(x,y,z);
                  }
                  , but if you want to use pointer to do this then remember that C++ doesnt have garbage collector and that you will have to free the memory by yourself by using delete. Also if you want to share references between instances of triangle note that reference class members must be initialized in the constructors initializer list and ofc, once initialized they cant be reset to reffer to some other object of their type.

                  Regards,
                  Savage

                  Comment

                  • Gangreen
                    New Member
                    • Feb 2008
                    • 98

                    #10
                    "if you want to share references between instances of triangle note that reference class members must be initialized in the constructors initializer list and ofc, once initialized they cant be reset to reffer to some other object of their type."

                    Could you elaborate? I just now rewrote the header like this to allow the sharing of vertices. Is it correct?

                    Code:
                    class Triangle: public rendering::HitAble {
                        public:
                    	Vertex* v1,v2,v3;
                    
                    	Triangle(): v1(one), v2(two), v3(three){};
                            ...other stuff
                    Thanks for the help.

                    Comment

                    • Savage
                      Recognized Expert Top Contributor
                      • Feb 2007
                      • 1759

                      #11
                      If you are going to use pointers then this is fine if one,two,three are pointers as well to a Vertex.. if they are still references then you need to use address-of operator(&) infront of one,two and three to properly initialize v1,v2,v3 pointers(or change the constructor to accept pointers instead of references) If what you are building is some small project you'll be fine by doing like this, if its going to be something bigger those reference sharings can really become a headache, so you might want to use handler class which track how many references are there to a single object. Here is a solid example of how to use them.

                      Regards,
                      Savage

                      Comment

                      • Gangreen
                        New Member
                        • Feb 2008
                        • 98

                        #12
                        Thanks, I'll look into it.
                        I appreciate the help

                        Comment

                        Working...