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.
Related
I'm trying to create an abstract class for ordinary differential equations, and have its independent variable use a different name in the inheriting classes. How do I go about that?
I don't want to allocate more memory for the renaming of the variable, i.e. create a new variable or a pointer to the base variable, as that's counterproductive. I just want to be able to access it with a different name in my inheriting classes, so that it's easier to know what the independent variable represents.
Mayhap a better question is, does the functionality of variable name overriding even exist in C++?
To give some code:
class ODE {
private:
int numEqns
double* q; // dependent variables
public:
double s; // independent variable
ODE(int numEqns) {
this->numEqns = numEqns;
this->q = new double[numEqns];
}
SetQOfIdxTo(int idx, double val) {
this->q[idx] = val;
}
};
class SpringODE : public ODE {
public:
double mass;
double c; // damping coefficient
double k; // spring constant
double d0; // initial deflection
SpringODE(double mass, double c, double k, double d0) : ODE(2) {
this->mass = mass;
this->c = c;
this->k = k;
this->d0 = d0;
time = 0.0;
SetQOfIdxTo(0, 0.0);
SetQOfIdxTo(1, d0);
}
};
The code is based on the one given in Grant Palmer's book "Physics for Game Programmers". The book in question being why I'm asking this question, as out of nowhere the time variable's Get function returns the base classes' GetS() function, which just returns "s" (albeit the code in the book is written in Java).
I have the below structures in my C++ code.
struct XYZ {
double x;
double y;
double z;
};
struct Data {
XYZ xyz_point;
double item_1;
double item_2;
double item_3;
};
In my code I create a vector of structure Data.
std::vector<Data> data_vector;
for (i = 0; i < 5; i++) {
Data data_point_1;
data_point_1.xyz_point.x = 10.0;
data_point_1.xyz_point.y = 11.0;
data_point_1.xyz_point.z = 12.0;
data_point_1.item_1 = 13.0;
data_point_1.item_2 = 14.0;
data_point_1.item_3 = 15.0;
data_vector.push_back(data_point_1);
}
Code build successful without any errors, however during the CPP_Check I get the below warnings/error. data_point_1 does not have the field x, y and z.
[test.cc:122]: (error: uninitStructMember) Uninitialized struct member: data_point_1.x
[test.cc:122]: (error: uninitStructMember) Uninitialized struct member: data_point_1.y
[test.cc:122]: (error: uninitStructMember) Uninitialized struct member: data_point_1.z
Could you please help me to resolve this.
Thank you,
push_back requires a default constructor. The compiler is able to supply that, but it doesn't initialise the doubles.
CPP_Check is spotting that.
One fix is to use emplace_back instead with the initialiser-list syntax. That doesn't require a default constructor. Another option is to supply a default constructor that initialises the members.
I am trying to use a class that I have written in another class. The problem is I am having difficulty using anything but the default parameters/constructor from the original class.
I have simplified the classes below to show what I am trying to achieve (I have tried all the variations on this I could think of but I think fundamentally I do not understand what's going on).
When I call class_two through class_one I want to use my own values for the calculation. However when I try this I just get the default parameters written in class_two.
class class_one {
private:
double a;
class_two class2;
public:
class_one(double A = 0.5, double B = 0.2) {
a = A;
class2 = class_two(b);
}
double calculation(){
return A*class2.get_b();
}
}
Where class_two would be,
class class_two {
private:
double b;
public:
class_two(double B = 0.5){
b = B;
}
double get_b(){
return b;
}
}
Example of what I am trying to run,
class_one().calculation();
actual output: A*B = 0.5 * 0.5 (Where the B values comes from class_two)
desired output: A*B = 0.5 * 0.2 (Where the B values comes from class_one)
Apologies this seems like a super simple question but I cannot get it to work!
When the constructor of a class is called, then - before its body starts executing - all of its data members are initialized. That means that for `class_two, the default constructor is called for its creation, since you don't say anything different.
In order to achieve your goal, use an initialization list, like this:
class_one(double A = 0.5, double B = 0.2) : a(A), class_two(B) {
// leave it empty in this case
}
PS: I initialized a via the initializer list as well, which is unrelated to your question, but a good habit to have, since initialization of data members is usually done via the initialization list, and not in the body of the constructor itself.
My mistake was very dum and not very interesting.
Basically I was using class2 to assign variables but I was only reassigning class2 after I had done this. I hadn't realised this.
Thanks Holt for showing me that my problem was not where I thought it was and gsamaras and François Andrieux for explaining that it's best to use an initialization list for this scenario!
class class_one {
private:
double a;
class_two class2;
public:
class_one(double A = 0.5, double B = 0.2) {
a = A*set_a();
class2 = class_two(b);
}
double set_a(){
return class2.some_function();
}
double calculation(){
return A*class2.get_b();
}
}
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).
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.