Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to return a derived class from a base class method in C++?

I would like to do this:

class Derived;

class Base {
    virtual Derived f() = 0;
};

class Derived : public Base {
};

Of course this doesn't work since I can't return an incomplete type. But neither can I define Derived before base, since I can't inherit from an incomplete type either. I figure that I could use templates as a workaround (using Derived as a template argument to Base), but it seems a really ugly way of doing things. Might there be another way?

Elaboration: I'm writing a raytracer, and each Shape class has a function which returns its bounding box. However, I've made the BBox a subclass of Shape, so I can visualize it. Is this bad design?

like image 383
int3 Avatar asked Nov 27 '22 05:11

int3


2 Answers

There's nothing wrong with the code in your question. This

class Derived;

class Base {
    virtual Derived f() = 0;
};

class Derived : public Base {
    virtual Derived f() {return Derived();}
};

should compile just fine. However, callers of 'Base::f()' will need to have seen the definition of 'Derived`.

like image 166
sbi Avatar answered Dec 05 '22 11:12

sbi


You could use a pointer (or a reference):

class Derived;

class Base {
    virtual Derived *f() = 0;
};

class Derived : public Base {
};

But this is code smell to me. Why should anybody inheriting from this class need to know about another derived class? In fact, why should the base class be concerned with it's derivee's?

For your situation, you'll need to notice things that mgiht be a signal for bad design. Although it makes sense that your bounding box would derive from Shape, keep in mind, since Shape has a function that returns a bounding box, a bounding box will have a function that returns itself.

I'm not sure the best solution, but you could make BBox a separate class altogether, and perhaps give it a function akin to: Shape *as_shape(void) const, which would construct a class Box : public Shape with the same dimensions as the bounding box.

I still feel there is a better way, but I'm out of time for now, I'm sure someone else will think of a better solution.

like image 26
GManNickG Avatar answered Dec 05 '22 09:12

GManNickG