0

I have a virtual base class Shape:

class Shape {
public:
    virtual bool intersect(Ray& r, HitRecord& rec)=0;

    virtual Material material()=0;
};

I think its the so called "pure virtual" class. So I think I should not try to instantiate it at any time.

However, I have a struct HitRecord which stores a pointer to the subclasses of Shape and since I don't know what class exactly does this pointer points to, I define it by Shape*:

struct HitRecord {
    float t;
    vec3f p;    // point coord
    vec3f norm;
    Shape* obj;
};

I'm actually trying to build a ray tracer, so I have a intersect() to check if rays intersect shapes. And if the ray do not intersect any shape in the scene, the rec variable will no be changed, i.e. rec.obj is pointing to a Shape.

So every time this happens I will get a BAD_ACCESS error since **I want to access a member variable of rec.obj. It should work when rec.obj is pointing to a subclass of Shape, but not when it's pointing to Shape.

bool intersect(Ray& r, HitRecord& rec) {
        rec.t = 100;
        for (std::vector<Shape* >::iterator it = shapes.begin(); it != shapes.end(); ++it) {
            HitRecord tmpRec;
            if ((*it)->intersect(r, tmpRec) && tmpRec.t < rec.t) {
                rec = tmpRec;
            }
        }
}

So now I want to check if the pointer is pointing to the exact Shape base class. I tried dynamic_cast but is seems it's not for this kind of situation.

I was wondering if this is a "design problem" or not. If not, how do I check the pointer is pointing to Shape?

Pavel_K
  • 10,748
  • 13
  • 73
  • 186
jinglei
  • 3,269
  • 11
  • 27
  • 46
  • Maybe not what you were looking for, but many debuggers show the dynamic type when inspecting a base class pointer. – ComicSansMS Aug 12 '17 at 08:33
  • 2
    How could you arrive at the situation where `obj` does not point to a derived type of `Shape`? (other than it being `nullptr` or being uninitialized.) – juanchopanza Aug 12 '17 at 08:35
  • Sorry I'm new to c++. In my code, in `intersect()`, if `if` block is never reached, `rec` will not be updated. And when `rec` is passed into `intersect()` it's just been declared (`HitRecord rec;`). I'm not sure what `obj` is pointed to if I haven't assign if explicitly..? – jinglei Aug 12 '17 at 08:40
  • 2
    I think you should start by [reading some good books](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list). Your question doesn't make much sense as it stands. – juanchopanza Aug 12 '17 at 08:42
  • 2
    When a pointer isn't initialized it doesn't point *anywhere at all*. And it definitely does not point to an abstract base class, because such an object cannot exist. One solution might be to assign `nullptr` as a pointer value and test for that. – Bo Persson Aug 12 '17 at 08:59
  • 2
    I'm not sure I understand your concern. You're worrying about detecting if `rec` points at an instance of `Shape`, but `Shape` (since it is abstract i.e. it has a declared pure virtual function) can never be instantiated. This means, if `rec` points to an actual object, that object will always be an instance of a derived type, and not an instance of `Shape`. – Peter Aug 12 '17 at 09:08
  • Provide minimal, complete, and verifiable example. Your problem seems to be not where you are trying to find it. – Jeka Aug 12 '17 at 10:05

1 Answers1

1

You need to initialise your HitRecord's obj pointer to null otherwise it's pointing to a random memory address.

One way to achieve this is to add a constructor to the HitRecord struct :

struct HitRecord {
    HitRecord() : obj(0) {}
    float t;
    vec3f p;    // point coord
    vec3f norm;
    Shape* obj;
};

Then what to want to test is whether rec.obj is null.

Johan Boulé
  • 1,936
  • 15
  • 19