Inheritance and friend functions, accessing protected members from base class - c++

Let say that I have a big class Circle with a lot of members and functions. To proceed a large amount of data I decided to create class PotentialCirlce (with only 3 members - x, y, r), do most of preprocessing based on PotentialCirlce and in the last stage create objects Circle.
a) is it correct approach? do It influence on performance or rather should I use only Circle.
It seems to me that I can use inheritance:
class potentialCircle {
protected:
point_t center;
unsigned int radius;
public:
potentialCircle(int a, int b, unsigned int r) : center{ point_t(a,b) }, radius{ r } {}
potentialCircle() = delete;
potentialCircle(const potentialCircle&) = default;
potentialCircle(potentialCircle&&) = default;
potentialCircle& operator=(const potentialCircle&) = default;
potentialCircle& operator=(potentialCircle&&) = default;
virtual ~potentialCircle() = default;
};
class Circle : public potentialCircle {
// members detected based on Hough Circle Transform
//point_t center; // coordinates of center point
point_t alternative_center; // needed when center is out of frame
//unsigned int radius; // radius
// members calculated based on Flood Fill algorithm (more realistic)
unsigned int area = 0;
float diameter = 0;
float perimeter = 0;
....
};
b) where should I put method which needs to compare two difference objects? one object of type Circle and one of PotentialCirle?
currently, I have defined below function as part of Circle
bool Circle::is_greater(const std::pair<potentialCircle, int>& point_pair) const;
but I don't have access to protected data members of potentialCircle, although Circle is inheriting from potentialCircle.
Maybe I should defined is_greater() as part of namepsace and make it a friend to Circle and potentialCircle.
Do you have better idea?

There are not really a good approach to compare objects of different types as it make little sense in practice. What would be the purpose of such comparisons.
Now even if you have a single class, if the ordering is not intransic to the type, it would be better to use an external class for sorting.
class CircleDiameterLess
{
public:
bool operator()(const Circle &lhs, const Circle &rhs)
{
return lhs.diameter < rhs.diameter;
}
};
That way, you can have multiple ways to sort data and it play nice with STL.
Another problem with your code if that it make little sense to have a class circle with a diameter that derives from a class potentialCircle with a radius. Your code will be hard to maintain because it is hard to understand.
You want to store either the diameter or the radius and compute the other one.
unsigned int get_diameter() const { return radius * 2; }
Member like alternative_center make no sense. A circle has only one center. If your class does not respect basic expectations, it will make the code hard to maintain as nobody would known that a circle has 2 centers including you in 3 months!
In a case like yours, it make make sense to add public accessors.
class potentialCircle
{
public:
unsigned int get_radius() const { return radius; }
....
};
That way, you can still make data private (or sometime protected) while having read only access to it. That way, you can write you comparison function as you wish. And in practice, if you have a class that represent a circle, you usually want at least being able to get basic properties like radius, aread, bounding rectangle by the way of a function.
Another thing is that public derivation as your (from potentialCircle) would only make senses if you have other classes that derives from it. However, if this is the case, then how would you compare the other kind of circles?
Notes:
With C++ 20, three way comparison would be even better.

Related

How can my class be provided some information about its environment?

Here's a code sample I wrote with encapsulation and composition in mind:
class Bullet {
private:
Vector2 position;
Vector2 speed;
public:
void move(float time_delta) {
position += speed * time_delta;
}
};
Basically, there's just a projectile moving in nowhere. However, a bullet can actually e. g. ricochet off a wall, having its speed changed significantly. Is there a good way of considering such interactions? I neither want my Bullet to know about "higher-rank" classes (which are supposed to use it themselves) nor write a single-use solution like this one:
template<typename F> void move(float time_delta, F collision_checker);
UPDATE: worth reading if you want this question narrowed. Here's a simplified example of the wished logic for moving Bullets (I don't exactly mean the Bullet::move() member function!) and their interactions with other entities:
Vector2 destination = bullet.position + bullet.speed * time_delta;
if (std::optional<Creature> target = get_first_creature(bullet.position, destination)) {
// decrease Bullet::speed depending on the target (and calculate the damage)
} else if (std::optional<Wall> obstacle = get_first_wall(bullet.position, destination)) {
// calculate the ricochet changing Bullet::position and Bullet::speed
}
All pieces of code represented by comments are supposed to use some properties of the Creature and Wall classes.
From a design point of view, it is probably best if your bullet doesn't know how to detect when it's ... passing_through an obstacle (scnr). So it might be better to turn your Bullet class in to a struct, i.e. have it behave like a thing that is acted upon instead of a thing that acts.
You can still add your convenience function but have it be non-mutating:
struct Bullet {
Vector2 position;
Vector2 speed;
Vector2 move(float time_delta) const {
return position + speed * time_delta;
}
};
This way you can compute the collisions from the calling scope:
auto dest = bullet.move(dt);
while (std::optional<Collision> const col = detectCollision(bullet.position,dest)) {
bullet.position = col->intersectPoint;
bullet.speed = col->reflectedSpeed;
dest = col->reflectDest;
}
bullet.position = dest;
Here detectCollision checks whether the line from the bullet's current position to the new position dest intersects with any obstacle and computes the parameters of the reflection. Effectively you zig-zag your way to the destination that will result from all successive ping-pongs of the bullet with potential obstacles.

How can I access to derived members from a pure virtual base class function?

I want to have a Collider interface class in which will have a overloaded -> operator to have access directy to the BoxCollider derived class. I want to have access to the members of box collider through the interface and chnage the type of collider at run-time.
So I thought of using templates:
template<typename T>
class ColliderV2 {
public:
virtual T* operator ->() = 0;
};
class BoxColliderV2 : public ColliderV2<BoxColliderV2> {
public:
float width;
float height;
BoxColliderV2* operator ->() {
return this;
}
};
int main()
{
ColliderV2<BoxColliderV2>* col = new BoxColliderV2;
(*col)->width = 1;
}
This works. But templates , as far as I know, will generate a brand new Collider class in compile-time filling T with Box Collider, correct? Thats why it worked. But later it prevents me from changing the collider type. I also thought of just making a virtual Collider class with Collider* operator->() ; overload in the derived class BoxCollider* operator->() ;
But if I tried :
Collider<BoxCollider>* col = new BoxCollider;
(*col)->width = 1; // won't work
doesn't work since Collider is not BoxCollider. And I don't want to dynamic_cast every possible collider type I could have. So, what can be done here?
As you've already found out, this doesn't work. Templates and runtime behavior are kind of contradicting mechanics. You can't create a common base class and let it act like a generic pointer to give you access to its derived types' members.
An interface specifies a contract against which you can code. You don't code against a specific implementation but the interface, so the interface has to provide all the members that you'd like to access. In your case this would result in width and height beeing part of ColliderV2 instead of BoxColliderV2. However this defeates the logic you are trying to mimic.
There are a few approaches that you can take:
Either make your collider type a variant, like
using ColliderType = std::variant<BoxColliderV2, MyOtherCollider, ...>;
and check for the actual type when you want to access the member
ColliderType myCollider = /* generate */;
if (auto boxCollider = std::get_if<BoxColliderV2>(&myCollider); boxCollider)
boxCollider->width = 0;
Or, keep the base class that you have, remove the operator-> and the template and do a dynamic cast on it:
ColliderV2* col = new BoxColliderV2;
if (auto boxCollider = dynamic_cast<BoxColliderV2*>(col); boxCollider)
boxCollider->width = 0;
You can also hide details like width or height behind more generic functions that are part of the interface. For example:
class ColliderV2 {
public:
virtual void setBounds(float width, float height) = 0;
};
class BoxColliderV2 : public ColliderV2 {
public:
void setBounds(float width, float height) override {
this->width = width;
this->height = height;
}
private:
float width;
float height;
};
int main()
{
ColliderV2* col = new BoxColliderV2;
col->setBounds(1, 1);
}
What you are trying to do is discouraged by C++. What you are trying to do is to change the type of something based on the return value of a function. The type system is designed to stop you from writing code like this.
One important restriction of a function is that can only return one type-of-thing. You can return one of a list of things if you wrap those possibilities in a class, and return that. In C++17, a ready-made class for this is std::variant. The restriction on this is that the list of things must be fixed (or a closed-set). If you want an arbitrary set of return values (open-set), you must use a different approach. You must restate your problem in terms a function that is done on the return value.
class BoxColliderV2 : public MyBaseCollider {
public:
void SetWidth(float new_width) override;
};
You may find this video useful. The bit of interest starts at around 40 minutes (but watch the whole video if you can). If you are interested in advice, I would suggest starting with std::variant, and if it works, move to virtual functions. Problems like collision detection get really complicated really quickly, and you will almost certainly require double dispatch at some stage. Start simple, because it's only going to get more complicated.
These excerpts from the ISO-Guidelines may help
1. When you change the semantic meaning of an operator, you make it
harder for other programmers to understand you code. guideline.
2. Dynamic casting is verbose and ugly, but deliberately so, because dynamic casting is dangerous, and should stand out. guideline
I think you are approaching the problem from the wrong direction. The purpose of an interface is that you don't have to know about the exact type or the implementation.
For example: You are using Axis-Aligned Bounding Boxes for collision detection. So, even if your CircleCollider uses a radius, you are still able to calculate its width and height from it. Now, you don't have to worry about if you are dealing with a BoxCollider or a CircleCollider, you have everything to make a Bounding Box.
class Collider
{
public:
virtual float x() const = 0;
virtual float y() const = 0;
virtual float width() const = 0;
virtual float height() const = 0;
};
class BoxCollider : public Collider
{
// Implementation...
};
class CircleCollider : public Collider
{
// Implementation...
};
Of course, you are maybe using something else, and not AABBs. I just wanted to demonstrate how you can use interfaces effectively.

Implementing abstract 'overlaps' method for different shapes?

I have an abstract base class called Shape, which looks something like this:
class Shape {
public:
Shape(Point center);
virtual bool overlaps(Shape *other) = 0;
private:
Point m_center; // has getter&setter
};
I'm having problems with the overlaps(Shape *other); method; I have no idea how to implement it in subclasses.
Let's take two examples, (I will probably have no more than two or three shapes) Circle and Rect.
Basically what I've tried is to create a two overloads in both classes after using forward declaration to allow Circle and Rect to "know" each other:
virtual bool Rect::overlaps(Circle *other);
virtual bool Rect::overlaps(Rect *other);
virtual bool Circle::overlaps(Circle *other);
virtual bool Circle::overlaps(Rect *other) { return other->overlaps(this); }
It's now easy to implement the maths inside all the overloads; however, I will get an error cannot allocate an object of abstract type 'Circle' and note: virtual bool Unit::overlaps(Unit *).
This is because my Circle and Rect classes only have methods with Circle * and Rect * as their parameters, but none with Unit *.
I also tried forward declarating Circle and Rect in my shape.h, but since forward declarations aren't the same classes as my actual Circle and Rect, I will only get the same error.
Without removing the common base class, is there a way to implement such behavior?
Or is there a workaround to make it work?
Additional Information
I have a 2D World class which contains vector<Shape *> m_shapes; and I will need to see if two shapes overlap each other;
for (unsigned int i = 0; i < m_shapes.size(); i++) {
if (certainShape->overlaps(m_shapes[i])) {
collapse();
}
}
Welcome to multiple dispatch! Essentially, you are asking for a method that is virtual with respect to the runtime type of more than one object - in your case, the types of two shapes being tested for overlap.
There are several common ways of implementing double dispatch in C++: for example, you could use the visitor pattern, or make a map based on RTTI. Selecting one or the other is up to you.
If you decide to go with the visitor pattern, you make the Shape "visitable" by adding the visit method.
Here is an example of the visitor-based approach. It is admittedly rather verbose, but it also addresses a complex task, so it is fair for it to require lots of code. I stripped the example below to the bare minimum - only two shapes with no data members, and methods that do not do anything except printing. This should be sufficient to get you started, though:
#include <iostream>
using namespace std;
class ShapeVisitor;
struct Shape {
virtual void accept(ShapeVisitor& v) = 0;
virtual bool overlaps(Shape& other) = 0;
};
class Circle;
class Square;
struct ShapeVisitor {
virtual void visitCircle(Circle& c) = 0;
virtual void visitSquare(Square& s) = 0;
};
// These three methods do the actual work
bool checkOverlap(Square& s, Circle& c) {
cout << "Checking if square overlaps circle" << endl;
return false;
}
bool checkOverlap(Square& a, Square& b) {
cout << "Checking if square overlaps square" << endl;
return false;
}
bool checkOverlap(Circle& a, Circle& b) {
cout << "Checking if circle overlaps circle" << endl;
return false;
}
class Square : public Shape {
struct OverlapVisitor : public ShapeVisitor {
OverlapVisitor(Square& _my) : result(false), my(_my) {}
virtual void visitCircle(Circle& c) {
result = checkOverlap(my, c);
}
virtual void visitSquare(Square& s) {
result = checkOverlap(my, s);
}
bool result;
Square& my;
};
public:
virtual void accept(ShapeVisitor& v) {
v.visitSquare(*this);
}
virtual bool overlaps(Shape& other) {
OverlapVisitor v(*this);
other.accept(v);
return v.result;
}
};
class Circle : public Shape {
struct OverlapVisitor : public ShapeVisitor {
OverlapVisitor(Circle& _my) : result(false), my(_my) {}
virtual void visitCircle(Circle& c) {
result = checkOverlap(my, c);
}
virtual void visitSquare(Square& s) {
// Important: note how I switched the order of arguments
// compared to Square::OverlapVisitor! There is only one
// square/circle overlap function checker, and it expects
// the square to be the first argument.
result = checkOverlap(s, my);
}
bool result;
Circle& my;
};
public:
virtual void accept(ShapeVisitor& v) {
v.visitCircle(*this);
}
virtual bool overlaps(Shape& other) {
OverlapVisitor v(*this);
other.accept(v);
return v.result;
}
};
Here is this running demo on ideone.
With RTTI approach you would make a map<pair<type_info,type_info>,checker> where checker is a type of a function that takes two pointers to Shape, and returns true or false depending on whether or not the shapes overlap. You make one such function for each pair of object types, populate the map with pointers to these functions based on type_info of their expected parameter types, and use this map at runtime to call the desired function.
Item 31 of the More Effective C++ book explains both these approaches in depth, with some great examples. In fact, the use case discussed in the book, detecting collisions between a pair of game objects, is similar to the one that you are implementing.
What you need is a "how big is other" type function. If we make it real simple, and just use a bounding box (a rectangle that is big enough to cover the entire shape), then we could do something like this:
(For simplicy, I'm using rect as a term for a rectangle)
class Shape
{
...
virtual rect BoundingBox() = 0;
bool overlaps(const Shape& other)
{
return BoundingBox.FitsInside(other.BoundingBox());
}
};
Obviously, you'll then have to write the function of fitsinside for two rectangles and BoundingBox for each shape, but it shouldn't be too hard.
To make a "is this Star completely covered by this Oval?" makes for a slightly more challenging solution [you will need to have a complete outline of both shapes, and an Oval outline may be quite a lot of points to be precisely oval].
Making the subclasses know about each other is a bad idea. If you want pixel-perfect collision, then you are going to have to iterate through every pixel in the shape and compare with the other shape's pixels. Create a virtual function to get a pixel N from the shape, where N is an index, and another function to return the number of pixels. For each pixel N in the current shape, compare with all pixels 0..Nmax in the other shape for collision.
The order of pixels from the index N can be any order. If you alternate pixels between different sides of the shape over nearby N, and start with the outer pixels first, you may be more likely to detect a collision on a lower N.
Now this simple approach is slow, especially if you have many shapes. The solution is to use a cheaper algorithm to check whether the perfect algorithm is necessary. A rectangle bounding box is the cheapest way. Work out the coordinates of a rectangle which is just large enough to hold your shape. I don't know how to work this out for a circle (geometry not my strong suit). You could even cache the bounding box sizes in the class to prevent recalculation for complex shapes. Checking whether two rectangles overlap is very quick and easy.
Only then move onto the costly algorithm if the bounding boxes overlap.
You can make faster checks between certain pairs of objects. For example, two rectangles overlap if their bounding boxes do. It's overkill to move onto pixel comparison. But you may not need this level of performance.

C++ public and private datatypes

I am currently working on Chapter 7 in the book "Starting Out With C++ Early Objects" by the Pearson printing company.
I am unable to understand the function of the variable 'r' in this class declaration:
class Circle
{ private:
double radius;
public:
void setRadius(double r)
{ radius = r; }
double getArea()
{ return 3.14 * pow(radius, 2); }
};
Why can't I just write the 'radius' variable like this?
class Circle
{ private:
double radius;
double getArea()
{ return 3.14 * pow(radius, 2); }
};
I don't understand the function of the
public:
void setRadius(double r)
{ radius = r; }
Statement.
The technical reason is "because radius is private, hence inaccessible from outside the class".
So a change to radius must be some how managed by a public member function like SetRadius.
If the question now becomes "why designers did it that way, and did not simple make radius public?", well ... this is a never ending debate about how a proper object-oriented design should be an what has to be public and what not inside an object.
Traditional OOP school tends to make all data "private" and access or modify them through a variety of function to enforce what they call "encapsulation", and to have life easier in case the interface need to be extended to support eventual callbacks or events.
In this trivial simple case, well... all looks like a waste of energy (and without proper compiler optimization IS a waste of energy! In true physical sense). But may be they needed a uniform interface with something else.
As the functional behaviour of private is explained in other answers, directly accesing a private member outside the class will give you a compile-time error.
If you are asking why do we use setter functions and make some members private is a matter of design. For example; if you need the radius to be always positive number, you can write the set function as;
void setRadius(double r)
{
if(radius >= 0)
radius = r;
else
radius = 0;
}
Thus, you will have control over the values of the member when they are tried to be modified outside the class.
The radius is private. Without that function, you would not be able to set the radius from outside of the class. In order for the class to be useful, you would most likely want to be able to create objects of the type Circle and set their radius. Thus, you need some type of function in order to set that radius.
The easiest and most reasonable way to solve this is to supply a public member function inside the class Circle itself.
This can most easily be done using a setter, such as what you have shown. This allows you to set, and later change, the radius.
void SetRadius(float r)
{
radius = r;
}
You could also supply an extra argument to the constructor to ensure that a Circle always has its radius initialized with a user-supplied value, or at least set a default value in the declaration of radius (in C++11).
The concept of public private that no one can access the private variables just the class methods, and you can only access the public methods from your main function so ,the function setRadius is responsible to set the private variable of the radius
public:
void setRadius(double r)
{ radius = r; }
because the radius is a private variable so you have to create a public function inside the class to set that variable so you can set the radius when you create Circle object by :
this will work to set the radius in the main
Circle * test = new Circle;
test.setRadius(7);
but if you tried to set the radius directly by :
Circle * test = new Circle;
test.radius = 7;
it will crash the program Cannot access class private method

Best way to alias methods of member object? "Passthrough methods"

Consider the following code:
class Rectangle
{
public:
// Constructors
Rectangle(){ init(0,0); }
Rectangle(int h, int w){ init(h,w); }
// Methods
void init(int h, int w)
{
_h = h;
_w = w;
}
// Getters / Setters
double get_h(void){ return _h; }
double get_w(void){ return _w; }
void set_h(double h){ _h = h; }
void set_w(double w){ _w = w; }
std::string get_name(void){ return _name; }
void set_name(std::string name){ _name = name; }
private:
// Private Members
int _h, _w;
std::string _name;
};
class House
{
public:
// <BEGIN PASSTHROUGHS>
std::string get_b_name(void){ return _base.get_name() };
std::string get_r_name(void){ return _roof.get_name() };
void set_b_name(std::string name){ _base.set_name(name); }
void set_r_name(std::string name){ _roof.set_name(name); }
// </END PASSTHROUGHS>
private:
// Private Members
Rectangle _base;
Triangle _roof;
};
This code works fine.
My question deals with the "passthrough" functions in the House class, enclosed by the PASSTHROUGHS tags. Is this the best way to do this? The arguments and return types will always match and there is no "intelligence" in these passthrough functions other than to make things cleaner and more straightforward.
My instinct would be something like one of the following:
get_b_name = _base.get_name;
// OR
std::string get_b_name(void) = _base.get_name;
... but neither seem to work unfortunately and it was only wishful thinking in the first place. If there are no easier options, telling me that is fine too. Thanks!
The problem, I think, is conceptual. Your design is quite un-object oriented in that the house does not represent an entity, but rather provides a bit of glue around the components. From that standpoint, it would make more sense to provide accessors to the elements, rather than pass-through functions:
class House {
Rectangle _base;
Triangle _roof;
public:
const Rectangle& base() const {
return _base;
}
const Triangle& roof() const {
return _roof;
}
};
I imagine that this is just a toy example, but the same reasoning applies: a class should represent an entity on which a set of operations are preformed, in some cases those operations might be implemented in terms of internal subobjects, but they are still operations on the type, and how they are gathered is an implementation detail.
Consider:
class House {
Thermostat t;
public:
int temperature() const {
return t.temperature();
}
};
From the user point of view the house has a temperature that can be read, and in this particular implementation, it is read from a thermostat that is a member. But that is an implementation detail. You might want to later install more thermostats in the house and substitute the single reading by an average of the readings, but that will not change the fact that the entity House (in this model) has a temperature.
That is, you should not be thinking in implementing pass-through functions, but rather on implementing features of the type. If the implementation happens to be a single forwarding to an internal method, that is fine.
But if the type contains internal members and it makes sense to access properties of the members, consider that it might be that you actual type should just provide access to its internal members. Consider that you want to move a piano inside the house, then you might just provide access to the door member and let the user check:
class House {
Door d;
public:
Door const & door() const {
return d;
}
};
bool can_enter_piano( House const & h, Piano const & p ) {
return h.door().width() > p.size();
}
There is no need to provide House::get_door_width(), and House::get_door_color() so that you can describe the entrance to a friend, and House::get_door_handle() so that they can know when they arrive...
That's possibly because your design is contradictory. Why on earth would you make a public member variable, then write a function that just forwards to one of that variable's functions? As a user of your class, I'd just call the function on the public variable myself. You're just confusing me by providing two ways to do the same thing. Or write getters and setters for a Rectangle class? That thing is just a bunch of variables, and doesn't need any getters and setters. You're not exactly going to inherit from it, and you can't really change the internal logic and maintain the same semantics, so it's very meaningless to not just make the variables public.
The Rectangle class needs a very healthy dose of YAGNI, and the House class just needs to look at itself again. The fact that there's no intelligence in the "passthrough" methods should be a huge alarm bell telling you that they are quite probably redundant and not helpful- especially since you can't change the public variables without breaking your interface anyway, it's not like the getters and setters are decreasing coupling or anything like that.
Methods should perform logic, or in the very least case, exist where logic might have to be done.