I need to create and array of DIFFERENT kinds of objects. For instance, in Java, I can do something like this ...

// scene objects 
Sphere scene_sphere = new Sphere();
Plane scene_plane = new Plane();
Object[] scene_objects = {scene_sphere, scene_plane};

in my program, both the Sphere class and the Plane class have a method called findIntersection(ray), which do different things, but both return a float, and then I can loop through my scene objects and call the method on any object in the array like this ...

Object[] intersections;
for (int index = 0; index < scene_objects.length(); index++) {
    intersections[index] = scene_objects[index].findIntersection(ray);
}

So far, with c++, all I know how to do is create a super class called Object and make both the Sphere and Plane classes inherit from the Object class. The problem is, when I loop through my scene objects and call the findIntersection method, I get an error saying that the Object class doesn't have a method called findIntersection. So how do I pass the findIntersection call on to the Sphere or Plane? I've already tried something like this ...

class Object {
	public:

	// default constructor, no arguments
	Object ();
	
	float findIntersection(Ray ray) {
		return this.findIntersection(ray);
	}
};

But this doesn't work of course. Any help would be appreciated. Thanks.

Recommended Answers

All 5 Replies

First of all, the compiler knows only about functions in object class definition. In your try it will just recursively call Object::findIntersection (or would call it if you use this->findIntersection). But you can declare function as virtual, then function call will be resolved during the runtime. Google some more info about virtual functions to get accustomed to them.
You must also remember that array is just raw memory with constant size place reserved for every Object object. If you assign derived class to it and this class has different size than original, you can overwrite further objects. You should use array of pointers to Object().
If you are Java programmer then I think you should also get more experience with pointers (for example this) before going deeper.

First of all, the compiler knows only about functions in object class definition. In your try it will just recursively call Object::findIntersection (or would call it if you use this->findIntersection). But you can declare function as virtual, then function call will be resolved during the runtime. Google some more info about virtual functions to get accustomed to them.
You must also remember that array is just raw memory with constant size place reserved for every Object object. If you assign derived class to it and this class has different size than original, you can overwrite further objects. You should use array of pointers to Object().
If you are Java programmer then I think you should also get more experience with pointers (for example this) before going deeper.

couldn't I just have a findIntersection method in the Object class and override it in the Sphere and Plane classes?

No, unless it is virtual. In c++ you are closer to bare metal, often you must tell compiler exactly what you mean. Now it sees method on Object class instance and in program Object member function will be called. By adding keyword virtual you say that this function can be overloaded in children classes, so it will be checked in runtime. And remember about array of pointers. I recommend reading c++ faq, it is short, well indexed and quickly give very good information on subject and possible pitfalls.

#include <iostream>
#include <vector>

struct Objs {
   virtual float volume ()=0;
   virtual ~Objs () {}
 };

struct Sphere : Objs  {   
   float radius;
   Sphere (float r) : radius (r)  {}
   virtual float volume ()  {
      return  (4/3)* ((radius*radius*radius)*3.1415);
    }
 };

struct Cilinder : Objs  {
   float base_radius;
   float height;
   Cilinder (float b_r,float h) : base_radius(b_r) , height(h)  {}
   virtual float volume () {
      return ((base_radius*base_radius)*3.1415)*height;
    }
 };

int main ()  {
   std::vector<Objs*> obj_array;
   Sphere sphere(10);
   Cilinder cilinder (5,10);
   obj_array.push_back(dynamic_cast<Objs*>(&sphere));
   obj_array.push_back(dynamic_cast<Objs*>(&cilinder));
   for (std::vector<Objs*>::iterator i=obj_array.begin();
        i!=obj_array.end();++i)  {
           std::cout << (*i)->volume() << "\n";
     }
    
 }

So far, with c++, all I know how to do is create a super class called Object and make both the Sphere and Plane classes inherit from the Object class. The problem is, when I loop through my scene objects and call the findIntersection method, I get an error saying that the Object class doesn't have a method called findIntersection. So how do I pass the findIntersection call on to the Sphere or Plane?

First, unlike in Java, non-static member functions in C++ classes are not run-time polymorphic by default. Only functions declared as virtual are bound at run-time. So the base class should be something like

class Object
{
   // ....

   public :
      // ideally findIntersection would be 'pure', but ignore that nicety for now
      virtual float findIntersection( const Ray& ray ) const { return 0 ; }

      // a virtual destructor is mandatory in C++ for any class having a virtual function
      virtual ~Object() {}

   // ....
} ;

And then we can have derived classes which override Object::findIntersection.

class Sphere : public Object
{
   public :
      virtual float findIntersection( const Ray& ray ) const
      {
          float intersection ;

          // ...

          return intersection ;
      }
};

Second, In Java class Y { ... void foo( Object x ) { ... } ... } ; x is a reference to an object. C++ does not work that way; the default in C++ is value semantics. x doesn't refer to an object somewhere, you could say that x is the object. To get reference semantics in C++, you need to explicitly use references or pointers. (Neither of these are identical to references Java, but they are similar). In C++, when we write

void foobat( Object a, Sphere b )
{
   a = b ; // a is still an Object, not a Sphere
}

it results in 'slicing'. http://en.wikipedia.org/wiki/Object_slicing. Slicing would also take place in:

Object o ;
    Sphere s ;

    Object scene_objects[] = { o, s } ; // s is sliced to an object

With reference semantics, slicing does not take place, and you would get the expected behaviour.

Object* o = new Object() ;
    Sphere* s = new Sphere() ;

    Object* scene_objects[] = { o, s } ; // no slicing here
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.