Object's structure overriding defined methods? - c++

I have a class called Object:
class Object {
public:
Vector pos;
float emittance;
Vector diffuse;
virtual float intersection(Ray&) {};
virtual Vector getNormal(Vector&) {};
};
And another class which inherits it:
class Sphere: public Object {
public:
float radius;
virtual float intersection(Ray &ray) {
Vector distance;
float b, c, d;
distance = ray.origin - pos;
b = distance.dot(ray.direction);
c = distance.dot(distance) - radius*radius;
d = b*b - c;
cout << -b - sqrt(d);
if (d > 0.0) {
return -b - sqrt(d);
} else {
return false;
}
}
virtual Vector getNormal(Vector position) {
return (position - pos).norm();
}
};
When I compiled the program, I was expecting it to start spitting out tons and tons of lines of text. But for some reason, that whole method (the intersection() method) is never actually called at all!
Why is my intersection() function from the Sphere class not overriding the default on found in the Object class?

You did not declare the function as virtual and make sure that the method signature matches. Change it to:
class Object{
virtual float intersection(Ray) {};
virtual Vector getNormal(Vector) {};
}
class Sphere: public Object {
...
virtual float intersection(Ray ray) {
...

Firstly, the derived class takes a reference, and the Object class does not. Secondly, the Object declares them as non-const, and the Sphere defines them as const. These both mean that you're not actually overriding the same function.

Related

Passing object of base class to function of reference to derived class

I'm trying to write code which can find the distance between lots of different types of shapes. I've defined a base class Shape with a virtual distance(Shape& otherShape) function to find the distance to another shape and then want to define that for all my derived classes.
The problem is that there are lots of possible pairs of shapes, so my solution was to define a set of distance functions outside the classes (circle-circle, circle-square, square-tri etc.) and then call the corresponding one from the distance function. I've added a mini example of what I mean below, with just one derived class Circle to demonstrate the problem.
When I try and call my specific circleCircleDistance function I get an error because it can't convert the base class into the derived class. Is there any way I can address this or will my design as it stands just not work?
enum ShapeType{CIRCLE, SQUARE};
class Shape {
public:
ShapeType type;
virtual double distance(Shape& otherShape) = 0;
};
class Circle : public Shape {
public:
ShapeType type = CIRCLE;
double distance(Shape& otherShape) override;
};
double circleCircleDistance(Circle& circle1, Circle& cirlce2){
return 0; //pretend this does the calculation
};
double Circle::distance(Shape &otherShape) {
switch (otherShape.type){
case CIRCLE:
//Here I get the error
//cannot bind base class object of type Shape to derived class reference Circle& for 2nd argument
return circleCircleDistance(*this, otherShape);
}
}
You would have to cast the Shape& to a Circle&
return circleCircleDistance(*this, static_cast<Circle&>(otherShape));
As an aside, I'd handle your types a bit differently
class Shape {
public:
virtual ShapeType get_type() const = 0; // derived classes must override this
virtual double distance(Shape& otherShape) = 0;
};
class Circle : public Shape {
public:
ShapeType get_type() const override { return CIRCLE; } // here's your override
double distance(Shape& otherShape) override;
};
...
{
switch (otherShape.get_type()){
Otherwise you're going to get into a situation where type is shadowed from the derived/base classes depending how you access it.
Multiple dispatch is not natively supported in C++.
We only have single dispatch thanks to virtual method.
So you can implement double dispatch for your cases.
An (C++17) "alternative" option is to use std::variant, which has std::visit which implement multiple dispatch:
You can keep inheritance or drop it.
struct Circle {
Point center;
float radius;
};
struct Rectangle {
Point topLeft;
Point bottomRight
};
using Shape = std::variant<Square, Rectangle>;
double distance(const Square&, const Square&);
double distance(const Square&, const Rectangle&);
double distance(const Rectangle&, const Square&);
double distance(const Rectangle&, const Rectangle&);
double distance(const Shape& shape1, const Shape& shape2)
{
return std::visit([](const auto& shape1, const auto& shape2){
return distance(shape1, shape2);
},
shape1,
shape2);
}
In c++20 you could use template specialization with concepts for this kind of problem

Is it possible to generalize an object type in a helper function?

I have a class CLASS. Classes A and B are derived from CLASS. CLASS, and therefore A and B too, have a field to hold a pointer to an array of pointers to CLASS.
Say I have a member function of A that does some calculations, creating objects of type A throughout. Pointers to these objects are added to the array stored in the object that is calling the function. The function returns void and takes no arguments. In class B, I want to do the exact same calculations, except create objects of type B instead. I am trying to write a helper function that can be called in both locations, creating objects of type A in one place and of type B in the other.
The constructors of the two classes A and B are identical, because they are both derived classes from the same base class. In the class A version function, if object A(x, y, z) is created, I would want the class B version to create B(x, y, z), the constructor taking the exact same arguments it would have in the class A version. This goes for every object that gets created.
class CLASS {
public:
CLASS** array
int x, y;
CLASS(CLASS** arr, int xcoord, int ycoord);
virtual ~CLASS();
};
class A : public CLASS {
public:
A(CLASS** arr, int xcoord, int ycoord);
void foo();
virtual ~A();
};
class B : public CLASS {
public:
B(CLASS** arr, int xcoord, int ycoord);
void foo();
virtual ~B();
};
//in A.cpp, definition of foo()
void A::foo() {
int a = some value
if (some condition) { array[a + 1] = new A(array, (a + 1), y); }
else if (other condition) { array[a - 1] = new A(array, (a - 1), y); }
//etc.
}
//in B.cpp, definition of foo()
void B::foo() {
int a = some value
if (some condition) { array[a + 1] = new B(array, (a + 1), y); }
else if (other condition) { array[a - 1] = new B(array, (a - 1), y); }
//etc.
}
I am not too familiar with template functions, but as far as I understand them they allow you to change the type of the function arguments and the return, which does not seem to be useful here.
Is this possible to do efficiently? I know I can just copy and paste the code and change it to make B objects and have a switch to run one or the other, or just have one version in A and one in B, but I am trying to avoid using either of these methods.
It seems to me that using virtual functions for this would be good. But if you really want to you can get around it with some CRTP.
If we add a CLASS_IMPL class that holds the helper function and make it derive from CLASS.
template <typename T>
class CLASS_IMPL : public CLASS {
CLASS* makeNew (int x, int y) {
CLASS* ptr = new T(array, x, y);
return ptr;
}
}
Downside here is that we need to change A and B to use
class A : public CLASS_IMPL<A> {
class B : public CLASS_IMPL<B> {
Then you can go ahead and change B::foo to use it.
void B::foo() {
int a = some value
if (some condition) { array[a + 1] = makeNew(a + 1, y); }
else if (other condition) { array[a - 1] = makeNew(a - 1, y); }
//etc.
}

Class isn't abstract but I get Error C2259: cannot instantiate abstract class

I'm trying to implement a Strategy pattern in C++, but I get the following error:
Error 1 error C2259: 'LinearRootSolver' : cannot instantiate abstract class
Here's my code (the line where the error is, is marked with a comment).
Class that uses strategy pattern (context):
bool Isosurface::intersect(HitInfo& result, const Ray& ray, float tMin, float tMax) {
INumericalRootSolver *rootSolver = new LinearRootSolver(); // error here
[...]
}
And here's my strategy pattern classes:
class INumericalRootSolver {
public:
virtual void findRoot(Vector3* P, float a, float b, Ray& ray) = 0;
};
class LinearRootSolver : public INumericalRootSolver {
public:
void findRoot(Vector3& P, float a, float b, Ray& ray) {
[...]
}
};
I can't see why I get an error for trying to instantiate an abstract class in the intersect method at the top?
void findRoot(Vector3* P, float a, float b, Ray& ray) = 0;
//^^
and
void findRoot(Vector3& P, float a, float b, Ray& ray)
//^^
parameter type mismatch, so findRoot inherited form based class is still a pure virtual function (not overriding), which make the LinearRootSolver class an abstract class. When you do:
INumericalRootSolver *rootSolver = new LinearRootSolver();
it tries to create an object of abstract class, you got the compiler error.
Your definition for LinearRootSolver::findRoot has the wrong signature. In particular, the first argument should be a pointer according to the declaration in INumericalRootSolver:
void findRoot(Vector3* P, float a, float b, Ray& ray) {
// ^ Here
[...]
}
In C++11, you can avoid this mistake by using the override keyword:
void findRoot(Vector3& P, float a, float b, Ray& ray) override {
[...]
}
This wouldn't compile because the function doesn't override a function from the base class.
Your derived class uses references and your interface uses pointers.
You need to have the same method signature for both methods in order to get a proper override.

Polymorphism with new data members

I would like to write a function that can initialize and return objects of different classes using polymorphism. I also would like these classes to have different data members which may be called through the virtual function. What I wrote below might work. Could you check if I have some undefined behavior in there? Thank you! One thing I am worried about is that when I call "delete polypoint" at the end it will not free the data member "scale" that is unique to "CRectangle". If my code doesn't work is there a way to make it work?
class CPolygon {
protected:
int width, height;
public:
void set_values (int a, int b)
{ width=a; height=b; }
virtual int area ()
{ return (0); }
};
class CRectangle: public CPolygon {
public:
int scale;
int area ()
{ return (width * height * scale ); }
};
CPolygon *polytestinner()
{
CPolygon *polypoint = 0;
int consoleinput = 2;
if (consoleinput>1)
{
CRectangle *rectpoint = new CRectangle();
rectpoint->scale = 4;
polypoint = rectpoint;
}
polypoint->set_values(3,4);
return polypoint;
}
void polytest()
{
CPolygon *polypoint = polytestinner();
gstd::print<int>(polypoint->area());
delete polypoint;
}
int main()
{
polytest();
return 0;
}
Thank you!
I feel compelled to point out Andrei Alexandrescu's object factory architecture. It allows your architecture to grow without having to modify the factory every time you create a concrete type. It is based on a "callback register", and it is actually implemented as a generic component in some libraries. The code is below.
Live Code Example
#include<map>
#include<iostream>
#include<stdexcept>
// your typical base class
class Shape {
public:
virtual void Draw() const = 0;
// virtual destructor allows concrete types to implement their own
// destrucion mechanisms
virtual ~Shape() {}
};
// this factory architecture was suggested by Andrei Alexandrescu in
// his book "Modern C++ Design" --- read it to get the full
// explanation (and a more generic implementation); this is just an
// example
class ShapeFactory {
public:
// this typedef allows to "name" arbitrary functions which take no
// arguments and return a pointer to a Shape instance
typedef Shape* (*CreateShapeCallback)();
Shape* CreateShape(int ShapeId) {
// try to find the callback corresponding to the given shape id;
// if no shape id found, throw exception
CallbackMap::const_iterator it = m_callbacks.find(ShapeId);
if(it == m_callbacks.end()) {
throw std::runtime_error("unknown shape id");
} else {
// create the instance using the creator callback
return (it->second)();
}
}
bool RegisterShape(int ShapeId, CreateShapeCallback Creator) {
// returns true if shape was registered; false if it had already
// been registered
return m_callbacks.insert(CallbackMap::value_type(ShapeId, Creator)).second;
}
bool UnRegisterShape(int ShapeId) {
// returns true if shape was unregistered, false if it was not
// registered in the first place
return m_callbacks.erase(ShapeId) == 1;
}
private:
// the typedef simplifies the implementation
typedef std::map<int, CreateShapeCallback> CallbackMap;
// the callbacks are stored in a map int->callback (see typedef
// above)
CallbackMap m_callbacks;
};
// create some concrete shapes... you would do this in other CPP files
class Line : public Shape {
public:
void Draw() const {
std::cout<<"Drawing a line"<<std::endl;
}
};
// another concrete shape...
class Circle : public Shape {
public:
void Draw() const {
std::cout<<"Drawing a circle"<<std::endl;
}
};
// ... other concrete shapes...
enum ShapeIds {LINE=1, CIRCLE, COUNT};
Shape* CreateLine() { return new Line; }
Shape* CreateCircle() { return new Circle; }
int main() {
// suppose this is the "singleton" instance for the ShapeFactory
// (this is an example! Singletons are not implemented like this!)
ShapeFactory *factory = new ShapeFactory;
factory->RegisterShape(ShapeIds::LINE, CreateLine);
factory->RegisterShape(ShapeIds::CIRCLE, CreateCircle);
Shape* s1 = factory->CreateShape(ShapeIds::CIRCLE);
Shape* s2 = factory->CreateShape(ShapeIds::LINE);
s1->Draw();
s2->Draw();
// will throw an error
try {
Shape *s3 = factory->CreateShape(-1);
s3->Draw();
} catch(const std::exception& e) {
std::cout<<"caught exception: "<<e.what()<<std::endl;
}
return 0;
}
CPolygon needs a virtual destructor:
virtual ~CPolygon() {}
You have undefined behavior in your code:
CPolygon *polypoint;
delete polypoint;
deleting a base class pointer when there is no virtual destructor will result in undefined behavior.
Your CPolygon class and CRectangle classes have no destructors, though the compiler will generate default destructor for you in this case, but they are not virtual by default. Therefore, you need to at least define a virtual destructor for your base class, i.e., CPolygon.

Adding class functionality via composition

Suppose we have an abstract class Element from which classes Triangle and Quadrilateral are derived from.
Suppose yet that these classes are used in conjunction with interpolation methods that depend on the shape of the element. So, basically we create an abstract class InterpolationElement from which we derive InterpolationTriangle and InterpolationQuadrilateral.
Then, to include the interpolation functionality in the Triangle and Quadrilateral classes, we add a const-reference data member in class Element of type InterpolationElement, that is:
class Element
{
public:
Element(const InterpolationElement& interp);
const InterpolationElement& getInterpolation() const;
private:
const InterpolationElement& interpolation;
};
We then create a method (as described by Scott Meyers, Effective C++) that instanciate a local static object of class InterpolationTriangle as
const InterpolationTriangle& getInterpolationTriangle()
{
static InterpolationTriangle interpolationTriangle;
return interpolationTriangle;
}
So that class Triangle can be constructed like:
class Triangle : public Element
{
public:
Triangle() : Element( getInterpolationTriangle() ) {}
};
Here is my question: is this approach correct in order to incorporate interpolation methods on my class Element? Is this used in professional scenarios?
I could implement directly all the interpolation methods on class Element (as pure virtual) and the override them in the derived classes Triangle and Quadrilateral. However, this approach seems to me to be cumbersome, since every time I need to improve or implement new interpolation functionalities I would have to do that on these classes. Moreover, the classes get bigger and bigger (many methods) using this approach.
I would like to hear from you some tips and comments
Thanks in advance.
Additional details:
class InterpolationElement
{
public:
InterpolationElement();
virtual double interpolationMethod1(...) = 0;
:
virtual double interpolationMethodN(...) = 0;
}
class InterpolationTriangle : public InterpolationElement
{
public:
InterpolationTriangle () {}
virtual double interpolationMethod1(...) { // interpolation for triangle }
:
virtual double interpolationMethodN(...) { // interpolation for triangle }
}
class InterpolationQuadrilateral : public InterpolationElement
{
public:
InterpolationTriangle () {}
virtual double interpolationMethod1(...) { // interpolation for quadrilateral}
:
virtual double interpolationMethod1(...) { // interpolation for quadrilateral}
}
The classes are used in conjunction with interpolation methods. Why do those methods need to be in a singleton object? The singleton here looks very problematic.
class Element
{
public:
virtual double interpolationMethod1(...) = 0;
:
virtual double interpolationMethodN(...) = 0;
};
class Triangle : public Element
{
public:
virtual double interpolationMethod1(...) { // interpolation for triangle }
:
virtual double interpolationMethodN(...) { // interpolation for triangle }
}
Also, welcome to SO!
This is reminiscent of a question that I had answered here. The same idea about the separation of data containers and the strategies.
There is one little issue with your proposal: you have added an interpolation related method to your base class and you've changed the constructor...
So first of all, if you wish to do it this way, here is how you should do it:
class Element
{
public:
private:
// similar signature to a `clone` method
virtual InterpolationElement* interpolation() const = 0;
};
class Triangle
{
public:
private:
virtual InterpolationTriangle* interpolation() const
{
return new InterpolationTriangle();
}
};
There are 2 advantages here:
It's no longer necessary to change the constructor of each of the derived objects
The strategy object is no longer const, which allows it to maintain state during the computation... like a reference to the current object being interpolated.
However, this still requires to change the Element class, and each of its derived classes. Doesn't it bother you ;) ?
Well, it's time (for once) to call upon a Design Pattern: Visitor.
It's a little different from the strategy idea, relying on double dispatch to work properly. However it allows you to tweak the hierarchy of Elements ONCE (with an accept method) and then to add as many operations as you wish. And that is great.
You can always mess a little bit with templates.
First we have a top class.
class Element {
public:
virtual void calculate() const = 0;
};
... but then we also have a class in the middle of the hierarchy which is actually a template. Template can't be the top level class, as templates with different parameters are different classes. The idea is that we give an interpolation class as a type parameter to the element.
template <typename Interpolation>
class Element_Impl : public Element {
protected:
Interpolation m_interpolation;
};
And interpolation classes. Notice, they aren't siblings, because they don't need to.
class InterpolationTriangle {
public:
double interpolate(double a, double b) const {
std::cout << "interpolation triangle" << std::endl;
}
};
class InterpolationQuadrilateral {
public:
double interpolate(double a, double b) const {
std::cout << "interpolation quadrilateral" << std::endl;
}
};
And finally the real elements and the small main procedure.
class Triangle : public Element_Impl<InterpolationTriangle> {
public:
void calculate() const {
m_interpolation.interpolate(1.0, 2.0);
}
};
class Quadrilateral : public Element_Impl<InterpolationQuadrilateral> {
public:
void calculate() const {
m_interpolation.interpolate(2.0, 3.0);
}
};
int main() {
const Element &a = Triangle();
const Element &b = Quadrilateral();
a.calculate();
b.calculate();
}
Summary:
you can easily switch interpolation class for each element if needed.
there aren't double vtable access (first for Element's calculate and then for InterpolationElement's intepolate methods) as in the Matthieu's example. Each element knows at compile time which interpolation class it is using.
Element_Impl is an ugly bit, but it saves us from copypasta. You can expand it even further by implementing interpolation method wrappers
http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern
One way is to use static methods, and defining a wrapper in Element_Impl - still only in one place.
class Element {
public:
virtual void calculate() const = 0;
};
template <typename Interpolation>
class Element_Impl : public Element {
protected:
void interpolate(double, double) const {
Interpolation::interpolate(1, 1);
}
};
class InterpolationTriangle {
public:
static double interpolate(double a, double b) {
std::cout << "interpolation triangle" << std::endl;
}
};
class InterpolationQuadrilateral {
public:
static double interpolate(double a, double b) {
std::cout << "interpolation quadrilateral" << std::endl;
}
};
class Triangle : public Element_Impl<InterpolationTriangle> {
public:
void calculate() const {
interpolate(1.0, 2.0);
}
};
class Quadrilateral : public Element_Impl<InterpolationQuadrilateral> {
public:
void calculate() const {
interpolate(2.0, 3.0);
}
};
int main() {
const Element &a = Triangle();
const Element &b = Quadrilateral();
a.calculate();
b.calculate();
}
What first comes to my mind is the GoF Design Pattern Visitor
From what I understand of your problem, this pattern is conceived to exactly solve this issue.
Each Visitor object defines an interpolation technique, or an algorithm to apply to your object.
Thus the Element class doesn't grow at all with each new functionnality. Once in place, the Visitor pattern enables to enrich functionnality without touching to the Base class definition.