What is wrong with the way I'm overriding this method? - c++

I'm trying to build a ray tracer. I have a class called Shape which I'm extending to the class of Sphere (and other shapes as well, like triangles). Shape has the method
virtual bool intersect(Ray) =0;
And so I create the Sphere class by
class Sphere : public Shape{
public:
Sphere(){};
bool intersect(Ray){/*code*/};
};
I have a main class which I use to create a list of Shape pointers. I create a Sphere pointer and do the following:
Sphere* sph = &Sphere();
shapes.emplace_front(sph); //shapes is a list of Shape pointers
Then when I want to trace the ray in another class I do the following:
for (std::list<Shape*>::iterator iter=shapes.begin(); iter != shapes.end(); ++iter) {
Shape* s = *iter;
bool hit = (*s).intersect(ray);
}
But I get the error that I cannot call intersect on a the virtual class Shape, even though it should be that *s points to a Sphere type object. What am I doing wrong with inheritance?

One problem is this:
Sphere *sph = &Sphere();
It creates a temporary object of type Sphere, stores a pointer to that temporary, then destroys the temporary. The result is nonsense.
Change it to this:
Sphere *sph = new Sphere();
things will work much better.

Related

C++ How to copy pointer data ( and all of its systems ) to another pointer of the same type?

It's easier for me to explain this kind of stuff in videogame terms. I'll try to be as clear as possible please bear with me...
I have a Bullet class that's made of different components, such as a Sprite component and a Transform Component... It would look something like this:
class Bullet
{
public:
Bullet( texture2D texture, Rectangle sourceRectangle, Rectangle destinationRectangle )
Bullet();
~Bullet();
// Returns a pointer to its sprite component so that I can use it wherever I want in the scene:
Sprite* const Sprite() const{ return this->sprite; }
// Setters:
void SetAngle( float new_angle ){ this->angle = new_angle; }
void SetSpeed( float new_speed ){ this->speed = new_speed; }
void SetRadius( float new_radius ){ this->radius = new_radius; }
private:
// Sprite component:
Sprite* sprite;
private:
// Regular member data:
float angle;
float speed;
float radius;
};
The sprite component is simply another class that holds a texture, source rectangle, destination rectangle, and some member functions to manipulate it (Move, Rotate, SetTexture, etc ). Nothing really special. It gets initialized within the constructor
What I need to do is to be able to copy one pointer to a bullet object entirely to another new pointer to a bullet, including the sprite component. Something like this:
// These arguments will be "fed" into the sprite component
Bullet* bullet1 = new Bullet( texture, sourceRect, destRect );
Bullet* bullet2 = new Bullet(); // Using default constructor.
*bullet2 = *bullet1;
Technically, doing it this way works. However, only the regular member data gets copied I think, but not the sprite component. It only points to the first bullet's sprite component. At least that's what I think is happening.
Hopefully I was clear explaining this issue, Thanks for taking the time.

Function inheritance and return types in C++

I'm learning C++ and I came across a problem that I can tackle with my previous programming experience (mainly C and Java; some but limited OOP experience), but I'd like to know what would be a proper, modern C++ solution to it. The problem concerns inheritance and derived classes' versions of a virtual function with different return types. Based on multiple Stack Overflow threads such a thing isn't possible. So how should I go about the following?
To practice C++ features, I'm writing a ray tracer. I have a virtual base class Object and derived classes Polyhedron and Polygon to describe the objects Rays of light can interact with. (In reality I have intermediate virtual classes Solid and Face, and derived classes Sphere, Cylinder, Circle alongside Polyhedron and Polygon, but let's forget about them here to keep things simple.) Currently, I've only implemented emission and absorption of light, i.e., a Ray only goes straight without any refraction or reflections. Absorption within a Polyhedron is proportional to intensity (exponential decay), so I have to figure out the objects a Ray passes through and integrate the Ray's intensity forward from its source to where it hits the detector. I have a vector std::vector<std::shared_ptr<Intersection>> intersections to store all these intersections of a Ray with the objects in a simulated scene. An intersection needs to contain the intersection Points, the intersected Polygon faces and the Polyhedron itself for a Polyhedron object, or alternatively the intersection Point and the Polygon face itself for a Polygon object. Consequently, I'd like to have derived classes Intersection_Polyhedron and Intersection_Polygon to override the call to Intersection::modulate_intensity(const double intensity_before) const which is supposed to return a Ray's intensity after passing the object in question. In other words, I'd like to avoid checking the type of the intersected objects and instead take advantage of inheritance when calculating the modulation to a Ray's intensity.
I would like to have each Ray simply loop through a vector std::vector<std::shared_ptr<Object>> objects containing all the objects in a simulated scene, call the virtual function Object::get_intersection(const Ray& ray) const and get either Intersection_Polyhedron or Intersection_Polygon in return based on the type of the intersection (if it's with a Polyhedron or a Polygon). Pointers to these derived intersection objects would be pushed back into intersections, intersections would be sorted based on the distance from the Ray's origin and then looped through to call and override Intersection::modulate_intensity() to determine a Ray's final intensity on the detector. To me, this would sound like the C++/OOP way of achieving this, but it doesn't seem possible because derived classes' versions of a base class's virtual function must all have the same return type. So how should I do it?
(Currently, I return a singular type of Intersection from get_intersection() for both Polyhedrons and Polygons. As its members, an Intersection has vectors for intersection Points and intersected std::shared_ptr<Polygon> faces, and an std::shared_ptr<Polyhedron> (which is a nullptr for Polygons as there's no bulk). To distinguish between intersections of Polyhedrons and Polygons, I simpy check if there are one or two intersection Points. This isn't too inelegant, but modern C++ has to offer a better way of achieving this with inheritance, right?)
Some very C++-like pseudocode to further clarify what I'd like to achieve:
// ...
// create objects in a scene
std::vector<std::shared_ptr<Object>> objects;
// ...
// find a ray's intersections with the objects
std::vector<std::shared_ptr<Intersection>> intersections;
for(const auto& object : objects) {
// virtual class Object's function overridden with that of Polyhedron or Polygon
// returns std::shared_ptr<Intersection_Polyhedron> or std::shared_ptr<Intersection_Polygon> based on type of object
auto intersection = object->get_intersection(ray);
intersections.push_back(intersection);
}
// sort the intersections with std::sort and a lambda expression
// ...
// calculate a ray's intensity
double intensity = 0.0;
for(const auto& intersection : intersections) {
// virtual class Intersection's function overridden with that of Intensity_Polyhedron or Intensity_Polygon
intensity = intersection->modulate_intensity(intensity);
}
// ...
Returning interface is fine in general:
class Ray;
struct Intersection
{
virtual ~Intersection() = default;
virtual double modulate_intensity(double intensity) = 0;
};
struct Intersection_Polygon : Intersection
{
double modulate_intensity(double intensity) override {/**/}
};
struct Intersection_Polyhedron : Intersection
{
double modulate_intensity(double intensity) override {/**/}
};
struct Object
{
virtual ~Object() = default;
virtual std::shared_ptr<Intersection> get_intersection(const Ray&) = 0;
};
struct Polygon : Object
{
std::shared_ptr<Intersection> get_intersection(const Ray&) override {
return std::make_shared<Intersection_Polygon>();
}
};
struct Polyhedron : Object
{
std::shared_ptr<Intersection> get_intersection(const Ray&) override {
return std::make_shared<Intersection_Polyhedron>();
}
};
Return type can be improved with covariance, but C++ only handle it for references and (non-smart) pointers. So it requires some boiler plate to simulate it for smart pointers:
struct Object
{
virtual ~Object() = default;
std::shared_ptr<Intersection> get_intersection(const Ray& ray)
{
return std::shared_ptr<Intersection>{get_intersection_ptr(ray)};
}
protected:
virtual Intersection* get_intersection_ptr(const Ray&) = 0;
};
struct Polygon : Object
{
std::shared_ptr<Intersection_Polygon> get_intersection(const Ray& ray)
{
return std::shared_ptr<Intersection_Polygon>{get_intersection_ptr(ray)};
}
protected:
Intersection_Polygon* get_intersection_ptr(const Ray&) override {
return new Intersection_Polygon();
}
};
template (possibly CRTP) might help to factorize boiler plate:
template <typename IntersectionType>
struct ObjectT : Object
{
std::shared_ptr<IntersectionType> get_intersection(const Ray& ray)
{
return std::shared_ptr<IntersectionType>{get_intersection_ptr(ray)};
}
protected:
IntersectionType* get_intersection_ptr(const Ray&) override {
return new IntersectionType();
}
};
struct Polygon : ObjectT<Intersection_Polygon> {};
struct Polyhedron : ObjectT<Intersection_Polyhedron> {};

store list of objects in class

Brand new to c++, trying to figure out how to create a class that I can store a list of objects in.
I have a surface class with subclasses such as triangles, circles, ect.
I'm trying to create a class called Scene, that I can store a list of all the surfaces.
Here's the header file for what I'm trying to do. How do you do this in c++?
class Scene
{
private:
//background color elements
float bgRed;
float bgGreen;
float bgBlue;
//array of different surfaces
Surface surfaces[]; //<--- What I want
public:
Scene();
addSurface(Surface s);
};
There are many possibilities, here's a easy one with a std::vector:
vector<Surface> surfaces;
...
addSurface(const Surface &s) //const and & are not strictly necessary, but better
{
surfaces.push_back(s);
}
...
//accessing like an array: surfaces[index]
//element count: surfaces.size()
This copies the passed objects (s) while inserting. If you want the same object, so that changes in the vector affect the object "outside" too (and vice-versa), you'll need an additional pointer.
Also note that copying of an child class object of Surface will result in a pure Surface, without the child class part (object slicing). If you need that part, you'll need a pointer too (if you don't have one already).
//pointer variant
vector<Surface*> surfaces;
...
addSurface(Surface &s)
{
surfaces.push_back(&s);
}

c++ creating object inside the class

I have created 2 classes.One is called Shape and its a virtual class.The other one is called Circle(I intend to create more of them like : triangle,square ....).I want to find circle area of the object,but that isnt important.Here is my problem.When I want to create an object like this :
vector<Shape *> mStack;
Shape *newShape = NULL;
newShape = new Circle(10.6);
mStack.push_back(newShape);
I can create it in the main file without problems.But when I try to create a function of it inside the "Shape" class..like this:
void Shape::Create()
{
Shape *newShape = NULL;
newShape = new Circle(10.6);
mStack.push_back(newShape);
}
I get following error: syntax error: identifier 'Circle'
... Here are my classes.
#pragma once
#include <vector>
using namespace std;
class Shape
{
private:
vector<Shape *> mStack;
public:
Shape();
~Shape(void);
virtual double Circle_area() = 0;
};
*********************************************************
#pragma once
#include "Shape.h"
class Circle : public Shape
{
private:
double m_r;
public:
Circle();
Circle(double r);
~Circle(void);
double Create();
double Circle_area();
};
Where is the problem here? How can I create an object inside the parent class? I hope you understand what I am trying to say. Thanks for the help.
Your Design is now improper. By proper design, your shape could act as an abstract class or base class for the real circles or rectangles. If then your design will be.,
And in main() you could maintain, a list of shapes vector<Shape *> mStack; which will not create problem. But you must not create circle or rectangle in shape. Thats a wrong design in my point of view.
Your base class is more than weird.
a base class should have virtual destructor
having a collection of itself is suspect for overreaching (you might have a CompositeShape down the hierarchy...)
It has a function named as a subclass. (could be shape_area() or just area())
Your implementation trouble is coming from this too: if the collection is not in shape, then create would not want to fill it, and problem gone.
From the provided info it's not clear where the content of create should go, may be the app, or may be some specific complex shape -- those could simply include all the required headers.

C++ overload resolution

I want to use inheritance to have an object treated in a different way depending on where in the hierarchy it falls
(similar to this C# question)
Assume you build a hierarchy of Shape objects like:
class Shape {} ;
class Sphere : public Shape {} ;
class Triangle : public Shape {} ; ...
You then equip a Ray class with methods like:
class Ray
{
Intersection intersects( const Sphere * s ) ;
Intersection intersects( const Triangle * t ) ;
};
You store an array of assorted Shape* of various types and call
vector<Shape*> shapes ; ...
//foreach shape..
Intersection int = ray.intersects( shapes[ i ] )
But you get the compiler error
error C2664: 'Intersection Ray::intersects(const Sphere *) const' : cannot convert parameter 1 from 'Shape *const ' to 'const Sphere *'
What did you do wrong?
Is the only way to do it the other way around, with
class Shape
{
virtual Intersection intersects( const Ray* ray )=0 ;
} ;
then each class override intersects? Then calls to
//foreach shape..
Intersection int = shapes[i]->intersects( ray ) ;
Can you do it the first way I showed or NEVER?
You have to do it the other way around. Overload resolution takes place at compile-time, when the type of what you're calling it with is a Shape*.
No, you can't do it the first way. Overload resolution in C++ is based on the static types of function arguments. It is resolved at compile time. In your example the static type is Shape * and there's no function in your class that would accept a Shape * (hence the error). The compiler doesn't care that your pointer might actually point to a Sphere at run time.
To implement what you are trying to implement you have to "channel" your calls through a facility that relies on dynamic types of the objects, i.e. through virtual function calls, which is what you do in your second example.
Your second example is a bit simplified, since the type of one of the objects involved is known at compile time (Ray). In a more complicated case both objects involved in an "intersection" could be dynamically type. If you care to handle something like that you can use so called "double dispatch" technique (search for it).
May be you can pull this with RTTI information. I haven't done it but it might be possible.
class Ray
{
Intersection intersects( const Sphere * s ) ;
Intersection intersects( const Triangle * t ) ;
Intersection intersects( const Shape * s ) {
//act on RTTI info, or
//use dynamic_cast to other types and check if the result is NULL or not
}
};