dynamic cast fails on downcasting from parent to child - c++

I have the following parent child simple classes:
class BoundBases{
public:
virtual ~BoundBases() { }
};
// Rectangular Bounds for tree
class RectBounds : public BoundBases{
public:
// x, y center point
double x, y;
double w, h;
~RectBounds(){ }
// (_x, _y): center of rectangle bound. (_w, _h): width and height
RectBounds(double _x, double _y, double _w, double _h){
x = _x;
y = _y;
w = _w;
h = _h;
}
//... more functions
};
I also have the following function structure:
void MyClass::init( BoundBases &bounds, std::vector<int> &colsPartitioned)
{
printf("init - new\n");
BoundBases * bPtr = &bounds;
RectBounds * rBounds = dynamic_cast<RectBounds *>(bPtr);
if(rBounds){
// do something
}else{
throw runtime_error("dynamic cast fail");
}
}
The dynamic cast is failing even though I call the function with RectBounds type as an argument. What is the reason?
FIXED:
The function calling init passed BoundBases by value, as follows:
MyClass2::MyClass2( BoundBases boundBases, std::vector<int> colsPartitioned) { // creates new table
// set up partition
partScheme_ -> setColsPartitioned(colsPartitioned);
partScheme_ -> setBoundBases(boundBases);
partScheme_ -> init(boundBases, colsPartitioned);
}
I changed the signature to pass by reference and it worked. (&boundBases). Can someone explain why is that? I am new to C/C++.

You need a reference here because dynamic_cast will only work if the real type of your variable is of type RectBounds like :
BoundBases* dummy = new Rectbound();
You can downcast here because the real type is Rectbound, so it will work.
If you pass it by value, it will create a copy of only the BoundBase part of your object, losing the information about your real type.
This problem is known as slicing

I'm not sure why you are surprised by that behavior. BoundBases passed by value is just a BoundBases. So dynamic_casting that to a child cannot make that a RectBounds. That's exactly what dynamic_cast is supposed to do.
If it worked differently: How would it be determining what e.g. x,y are if it's only given a BoundBases. This is not defined.

Related

Can't delete element from vector, attempting to reference deleted function

I am making my "version" of Space Invaders in C++ using SFML library but I have a problem when I try to delete an invader.
I have this error in my code:
Enemy &Enemy::operator =(const Enemy &)': attempting to reference a deleted function
I tried to check other solutions that were recommended in this forum but I either didn't understand them or it was a different case.
EnemyControler.cpp
EnemyControler::EnemyControler()
{
Enemy::Type types[] = {
Enemy::Type::Squid, Enemy::Type::Crab, Enemy::Type::Crab,
Enemy::Type::Octopus, Enemy::Type::Octopus
};
for (int y = 0; y < 5; y++) { // Add enemies to the vector
for (int x = 0; x < 11; x++){
float enemyX = x * 40 + (gapBetweenEnemies * x * 3) + Enemy::enemyWidth; // Make horizontal gap between them
float enemyY = y * 40 + (gapBetweenEnemies * y) + Enemy::enemyHeight; // Make vertical gap between them
enemies.emplace_back(sf::Vector2f{ enemyX, enemyY }, types[y]); // Add them to the vector
}
}
}
void EnemyControler::destroyEnemy()
{
for (auto iterator = begin(enemies); iterator != end(enemies);) {
auto& enemy = *iterator;
if (enemy.isAlive()) {
iterator++;
}
else {
iterator = enemies.erase(iterator);
}
}
}
Problem is in destroyEnemy function. Specifically in iterator = enemies.erase(iterator);
EnemyControler.h
class EnemyControler
{
public:
EnemyControler();
void destroyEnemy();
private:
const int gapBetweenEnemies = 10;
std::vector<Enemy> enemies;
};
Enemy.cpp
Enemy::Enemy(sf::Vector2f startingPosition, Type type) :
Collidable(enemyWidth, enemyHeight), newPosition(startingPosition), enemyType(type), startingPosition(startingPosition)
{
}
Enemy.h
class Enemy : public Collidable
{
public:
enum class Type // enum for different looking enemies
{
Crab, Octopus, Squid
};
Enemy(sf::Vector2f startingPosition, Type type);
constexpr static float enemyWidth = 30.0f;
constexpr static float enemyHeight = 30.0f;
private:
sf::Vector2f newPosition;
Type enemyType;
const sf::Vector2f startingPosition;
};
Collidable.cpp
Collidable::Collidable(float width, float height) :
spriteSize(width, height)
{
}
Collidable.h
class Collidable
{
public:
Collidable(float width, float height);
private:
sf::Vector2f spriteSize;
};
If there isn't an easy way of fixing this problem or this problem could be fixed only by rewriting all code maybe you could suggest another way of deleting invader from the vector.
If a class has a const member variable, then the copy assignment operator for that class operator= is default-deleted by the compiler.
From https://en.cppreference.com/w/cpp/language/copy_assignment :
A defaulted copy assignment operator for class T is defined as deleted if any of the following is true:
- T has a non-static data member of non-class type (or array thereof) that is const;
This is because the compiler can't guess what it means to copy assign object A into object B, if objects of their class contain a const member variable. Should the compiler just ignore that particular member variable? Should the compiler guess that you mean it to be const, except when copy assigning, then it's okay just this once - I'll look the other way? The compiler has no idea what you would prefer, so it just deletes it.
One option is to explicitly define a copy assignment operator for your class.
However, startingPosition is already declared private, so there's little chance of anything outside of the class inadvertently changing it. I recommend just removing the const specifier.
Why does the copy assignment operator matter? I'm trying to delete things, not copy assign them
When an element is erased from a vector, all elements in the vector "above" the erased element need to be moved down to fill the gap. This happens via the copy assignment operator.
From https://en.cppreference.com/w/cpp/container/vector/erase :
Complexity
Linear: the number of calls to the destructor of T is the same as the number of elements erased, the assignment operator of T is called the number of times equal to the number of elements in the vector after the erased elements

Passing class by reference doesn't change original

I have a class that handles rendering sprites, which has a Ball and Gun objects on it, sets their sprites, and renders them every frame. I want to pass in that ball object to gun, so that gun can fire when a user presses space (input is handled on gun). I tried pointers, and now passing by reference, but when I change it after passing it in it doesn't affect the original. In my main class I call gun.init(&ball) that I'll show here. Gun has a variable Ball mBall.
class Gun : public GameObj
{
public:
Gun()
:GameObj(), mWaitSecs(0)
{}
void Update();
void Init(Ball &ball); //init function that passes in ball?
private:
float mWaitSecs; //delay after firing beforeo you can move/fire
Ball mBall;
};
void Gun::Init(Ball &ball) {
mBall = ball;
}
[..] but when I change it after passing it in it doesn't affect the original.
Frankly, you have a basic misunderstanding. And to clear that up, I have to take a small detour.
Pass by value
void foo_value(int x) { x += 42; }
calling this function via
int y = 50;
foo_value(y);
will not change the value of y.
Pass by reference
void foo_ref(int& x) { x += 42; }
calling this function will modify y:
int y = 50;
foo_ref(y);
assert(y == 50+42);
Rebinding references
You cannot rebind references. That's why you cannot not initialize a reference:
int& y; // error
int x;
int& y = x; // ok
Once you have a reference you cannot make it refer to something else. You cannot "reassign" the reference:
int x = 0;
int& ref = x;
int y = 42;
ref = y; // same as x = y;
after the last line, ref is still a reference to x.
Your code
You do pass ball by reference, but your member mBall is not a reference. mBall is a copy of the ball refered to by ball. An example similar to your code is
void foo_copy_from_ref(int& x) {
int mx = x;
mx = 42;
}
Modifying a copy has no effect on the original, no matter if you made the copy from a reference.
You can have a reference to a Ball as member, but you have to initialize it in the constructor and you cannot make it refer to a different Ball later.

Structure constructor in other structure

I am trying to create Voronoi diagram for some given points. Each points have different attributes and I want to denote it as color. To map my own Point structure with Boost Point concept, I have written some code. I have the following setup:
struct Point {
double a;
double b;
Point(double x, double y) : a(x), b(y) {}
};
// This Point structure is mapped to Boost Point concept. Code emitted
I have another structure as :
struct Point_Collection {
Point xy(double x, double y);
short color;
};
Visual Studio created an automatic definition as :
Point Point_Collection::xy(double x, double y)
{
return Point();
}
Now if I try to instantiate an object of Point_collection as:
std::vector<Point_Collection> *test;
test = new std::vector<Point_Collection>();
Point_Collection xy_color;
for (int i = 0; i < 5000; i++) {
xy_color.xy(rand() % 1000, rand() % 1000);
xy_color.color = rand() % 17;
test->push_back(xy_color);
}
I get an error.
error C2512: 'Point': no appropriate default constructor available
Can someone point me in the right direction why is this happening?
Point xy(double x, double y); declares a member function in Point_Collection that is identified by xy, accepts two doubles and returns a Point object by value.
If you want a simple aggregate that holds a point, the C++11 and onward way would be to define it like this:
struct Point_Collection {
Point xy;
short color;
};
Point_Collection xy_color{ { rand()%100, rand()%100 }, static_cast<short>(rand()%16)};
The above is a simple aggregate initialization using value initialization syntax. You should prefer it for two reasons:
It will not allow narrowing conversions. (Which int to short is, therefore the cast).
It's easy to implement. It requires no typing if your class has all public members.
(Also rand has better alternatives in C++11, check out the header <random>)
If you don't have access to C++11, then you can either write a constructor for Point_Collection.
struct Point_Collection {
Point xy;
short color;
Point_Collection(Point xy, short color)
: xy(xy), color(color) {}
};
Point_Collection xy_color (Point(...,...), ...);
Or use aggregate initialization with more verbose syntax:
struct Point_Collection {
Point xy;
short color;
};
Point_Collection xy_color = { Point(rand()%100, rand()%100), rand()%16 };
(Since the above is C++03, rand()%16 will be silently converted to short, despite it being narrowing).

C++ struct default constructor mbed

I have this definition for my structure:
struct localframevelo
{
double ivelo; //i(x) component of velocity
double cvelo; //c(y) component of velocity
double rvelo; //r(z) component of velocity
double speed; //total magnitude of velocity
localframevelo()
{
ivelo = 0;
cvelo = 0;
rvelo = 0;
speed = 0;
}
localframevelo(double init_ivelo, double init_cvelo, double init_rvelo)
{
ivelo = init_ivelo;
cvelo = init_cvelo;
rvelo = init_rvelo;
speed = sqrt(pow(ivelo, 2.0) + pow(cvelo, 2.0) + pow(rvelo, 2.0));
}
};
Here is a class that I am trying to use the default constructor of localframevelo in:
class missionprofile
{
//misison waypoints structure************************
private:
double stdholdtime; // 0.25 second within tolerance radius to "reach" a waypoint
double stdtolrad; // 0.5 meter tolerance radius (error magnitude) to "be at" a waypoint
localframevelo stdvelo;
waypoint missionwaypoints[MAXLISTLENGTH];
int numwaypoints;
public:
missionprofile();
missionprofile(int points, double StdHoldTime, double StdTolRadius, localframevelo StdVelo);
};
Here is the implementation of the default constructor for the class that I am trying to call the localframevelo's default constructor:
missionprofile::missionprofile()
{
numwaypoints = 0;
stdholdtime = 0;
stdtolrad = 0;
stdvelo(); //ERROR
}
I get this error: call of an object of a class type without appropriate operator() or conversion functions to pointer-to-function type. I am using the mbed compiler, what is wrong with my code?
You can safely remove this line:
stdvelo();
In the context of a function body, this is interpreted as a call to the operator()() of an instance of localframevelo, not an initialization. The data member will be default constructed anyway without any explicit initialization. But what you should really be doing is to initialize your data members in the constructor's initialization list:
missionprofile::missionprofile()
: numwaypoints(),
stdholdtime(),
stdtolrad(),
stdvelo()
{
}
And similarly for localframevelo's constructors and the other missionprofile constructor.
When you write stdvelo(), the compiler sees stdvelo.operator()() and then complains when no such function exists.
The data member is going to be constructed anyway; you don't need the line at all.
Also, it's marginally faster to use initialization rather than assignment for your starting values (though chances are high that your compiler will optimize away the difference anyway).
So you'd use this, for example, for the second constructor:
localframevelo(double init_ivelo, double init_cvelo, double init_rvelo)
: ivelo(init_velo)
, cvelo(init_cvelo)
, rvelo(init_rvelo)
, speed(sqrt(pow(ivelo, 2.0) + pow(cvelo, 2.0) + pow(rvelo, 2.0)))
{}
For the first, you'd just use 0 instead of init_velo et al.

What is the best way to indicate that a double value has not been initialized?

I have a class CS which is to represent the co-ordinate system in 3D i.e.(x, y, z)
class CS
{
private:
double x;
double y;
double z;
}
CS::CS()
{
x = NULL;//this causes x = 0//i want the address of x to be 0x000000 & not x = 0
y = NULL;
z = NULL:
}
I want that the user can create a CS (0, 0, 0).
In the constructor i want to initialise the address of x, y & z to NULL.
this is to differentiate between the user defined (0, 0, 0) & the default value.
I am creating the objects of CS dynamically, so there is no point in using the following code:
class CS
{
private:
double *x;
double *y;
double *z;
}
CS:CS()
{
x = new double;
x = NULL;
//same for y & z
}
Primarily, i want to manually assign 0x000000 address to any variable(int or double or char) without using pointers.
any suggestions?
You can't change the positions of x,y,and z to be NULL, since there positions will always be offsets from the CS object. They will always exist. It's not that CS has an x like you have a car, it's like CS has an x like you have a head. You can't not have a head. If they were integers, you would have to make them pointers (like you said you didn't want to do), because that would be the only way to tell uninitialized from initialized. However, doubles have a magic value that is rarely used:
CS:CS()
: x(std::numeric_limits<double>::quiet_NaN())
: y(std::numeric_limits<double>::quiet_NaN())
: z(std::numeric_limits<double>::quiet_NaN())
{ }
Users probably won't be setting x, y, and z to (NOT A NUMBER) intentially.
Primarily, i want to manually assign 0x000000 address to any variable(int or double or char) without using pointers. any suggestions?
That's not what you want. What you want is the ability to detect whether a variable has been set or not.
Others have suggested things like using a specific floating-point value to detect the uninitialized state, but I suggest employing Boost.Optional. Consider:
class CS
{
private:
boost::optional<double> x;
boost::optional<double> y;
boost::optional<double> z;
}
boost::optional either stores the type you give to the template parameter or it stores nothing. You can test the difference with a simple boolean test:
if(x)
{
//Has data
}
else
{
//Has not been initialized
}
The downside is that accessing the data is a bit more complex:
x = 5.0; //Initialize the value. x now has data.
y = 4.0 * x; //Fails. x is not a double; it is an optional<double>.
y = 4.0 * (*x); //Compiles, but only works at runtime if x has a value.
You have several options:
Use pointers.
Use a boolean flag alongside each variable indicating whether the variable has been set.
If the range of allowable values is limited, you could use a special value to stand for "not set". For double, a not-a-number is often a natural candidate. For int and char it's often more tricky to pick a good value.
None of these options is indisputably better than the other two as they involve different tradeoffs. Take your pick.
Why can't you simply do this:
class CS
{
public:
// Constructs a CS initialized to 0, 0, 0
CS() : x(0), y(0), z(0), is_initialized(false) {}
// User defined values
CS(double newX, double newY, double newZ) : x(newX), y(newY), z(newZ), is_initialized(true) {}
private:
double x;
double y;
double z;
// If you need to know that this was initialized a certain way, you could use this suggestion from the comments:
bool is_initialized;
}
If I understand correctly, you want to be able to tell the difference between an invalid, default constructed CS and a valid one with values (0.0, 0.0, 0.0). This is exactly what boost::optional http://www.boost.org/doc/libs/1_47_0/libs/optional/doc/html/index.html is for.
You can't really represent it in the same number of bits without having a sentinel. If 0 is a valid number, then you can't use it. If you try and foist null handling into a value type you will have fundamentally incorrect and unmaintainable code.
When handling nulls properly you would expect to see an interface like this:
struct foo {
virtual ~foo() {}
virtual bool getX(double &val) = 0;
virtual bool getY(double &val) = 0;
virtual bool getZ(double &val) = 0;
};
The implementation can have a flag that it checks before access.
void some_func(foo *f) {
double x, y, z;
if (f->getX(x) && f->getY(y) && f->getZ(z)) {
cout << x << ", " << y << ", " << z << endl;
} else {
throw std::logic_error("expected some values here");
}
}
You don't want to use an invalid value and not know it. Having to check the return values is tedious obviously, but it gives you the most control. You could also have helpers or overloads that would throw if they weren't valid.
struct bar {
double getX() {
if (!valid)
throw std::logic_error("bar is not valid");
return x;
}
bool valid;
double x, y, z;
}
For me, the difference between foo and bar is that low level code handling the data shouldn't enforce a policy of whether the data is there or not. At higher levels of abstraction you can and should have expectations of whether the data should valid when you go to use it. The both can exist in a system, but foo is necessary.
One way to get the semantics of what you want would be to have the datatype of the coordinates be a type that carries with it a value indicating whether it has been assigned. Something like this.
template<typename T>
class CoordinateValue {
public:
CoordinateValue() : uninitialized(true), val(0) {}
CoordinateValue(T x) : uninitialized(false), val(x) {}
void setVal(T x) {val = x; uninitialized= false}
// Trivial getters
private:
T val;
bool uninitialized;
};
I'd prefer something like this over cuter methods unless memory is really scarce for some reason.
If the coordinates are either all default or all set, then you can have a single flag rather than a coordinate datatype that includes the flag.
I want that the user can create a CS (0, 0, 0). In the constructor i
want to initialise the address of x, y & z to NULL. this is to
differentiate between the user defined (0, 0, 0) & the default value.
I am creating the objects of CS dynamically, so there is no point in
using the following code:
This is the problem. Firstly, default value? What default value? Why should there be a default value? That's wrong. And secondly, it's fundamentally impossible for you to change the address of any variable.
What you want cannot be done and even if it could, it would be a horrendously bad idea.
You can't change the address of a variable. And you can't assign pointer values (like NULL, or nullptr in C++) to a variable of a non-pointer type, such as double.