Does this coding style belong to an older version of C++? - c++

I come across this code in my older books. I tried to run it in Visual Studio 2019, but it gave me an error:
volume function does not take zero arguments
Is this because the code is old, or the code is wrong?
#include<iostream>
using namespace std;
class Cylinder
{
private:
const double pi = 3.14;
double r, h;
public:
void ro(double radius) {
r = radius;
}
void ho(double height) {
h = height;
}
double volume(double r, double h)
{
return pi * r * r * h;
}
};
int main()
{
Cylinder s;
s.ro(1);
s.ho(2);
cout << s.volume();
return 0;
}

The code is wrong. The volume function is declared to take two double arguments and the C++ compiler expects it to be called that way.
I'm not aware of any C++ compiler of any age that would accept that code.
It looks like maybe the function is trying to use the member variables r and h, in which case you should probably remove the parameters from the declaration of volume.

The code is wrong.
When calling a function, you must pass in as many values as there are parameters declared. You can't skip parameters, unless they are declared with default values, which is not the case here.
Given the way main() is using Cylinder in this example, the 2 input parameters need to be removed completely, since they are shadowing the r and h class members that are being set by the ro() and ho() methods.
double volume()
{
return pi * r * r * h;
}
Now the call to cout << s.volume(); will work as expected.

I believe the code is wrong.
If you had default argument on the method.
E.g something like this:
double volume(double r = 0, double h = 0)
{
return pi * r * r * h;
}
It would work when you call it without parameters.

Related

c++ class inheritance issue

I am having some troubles with c++ inheritance and I cannot find the error. I have class that implements a simple unicycle kinematic model.
namespace kinematics{
class Unicycle{
// state variables
geometry_msgs::Pose2D _state; ///< position of the robot
// robot parameters
float _max_linear_vel; ///< maximum linear velocity, saturation
float _b; ///< output point offset
// integration variables
float _int_step; ///< integration step
protected:
void _updateOdometry(float dv, float tr);
void _ioLinearization(float vx, float vy, double &d, double &t);
public:
Unicycle();
Unicycle(float is, float b, float vmax, geometry_msgs::Pose2D initS);
};
}
Since a differential drive kinematic model is an extension to the unicycle I would like to implement using inheritance.
#include "unicycle/Unicycle.h"
class DiffDrive: public kinematics::Unicycle {
//robot parameters
float _wheel_radius; ///< wheel radius
float _wheel_separation; ///< distance between wheels
void _wheelSpeed(float dv, float tr, float &rs, float &ls);
public:
DiffDrive();
DiffDrive(float wr, float ws, geometry_msgs::Pose2D initS,
float ts, float vmax, float b);
};
I wrote the constructor in this way
DiffDrive::DiffDrive(float wr,
float ws,
geometry_msgs::Pose2D initS,
float ts,
float vmax,
float b)
:Unicycle(ts,b,vmax,initS), _wheel_radius{wr}, _wheel_separation{ws}{
}
However when I use the function _wheelSpeed()
void DiffDrive::_wheelSpeed(float dv, float tr, float &rs, float &ls){
ls = dv - _wheel_separation*tr/2.f;
ls = ls/_wheel_radius;
rs = _wheel_separation*tr/_wheel_radius + ls;
std::cout << "PARS: " << _wheel_separation << " - " << _wheel_radius << std::endl;
std::cout << "WHEELS: " << rs << " - " << ls << std::endl;
}
The value of _wheel_separation and _wheel_radius are different from what expected:
PARS: -179014 - 4.58631e-41
Even if the constructor is invoked with the following values:
wheel_radius = 0.02;
wheel_sep = 0.04;
_diff_drive = new DiffDrive(wheel_radius,wheel_sep,update_period,vel_max,offset);
Please help me understand what's wrong with my code.
Check out the differences between inheritance and composition.
Think of it this way:
Is a differential drive a unicycle or is a differential drive a part of a unicycle?
Doesn't inheritance make more sense in this way:
Cycle is a base class
Unicycle is a derived class
Tricycle is another derived class.
Differential drive is something that is a part of a unicycle.
I think if the design is correct, the rest will fall in place automatically. The values you are getting look like either uninitialised values or values of an object that was already destroyed (again uninitialised values.)
I figured out what was wrong. I remember that in Java it was allowed to invoke a constructor from another constructor so to hide some parameters and avoid to rewrite the entire initialization. For example:
constructor1(par 1, par2){
par3 = 0;
constructor2(par1,par2,par3);
}
I am not sure that this is correct, but that is what I thought.
Therefore I implemented my constructor in the following way
DiffDrive::DiffDrive(const float wr,
const float ws,
float ts,
float vmax,
float b):Unicycle(ts,b,vmax){
geometry_msgs::Pose2d initS;
initS.x = 0;
initS.y = 0;
initS.theta = 0;
DiffDrive(wr,ws,initS,ts,vmax,b);
}
Unfortunately this is not legal in C++, that returned the result of the instantiation of the outer constructor ignoring the inner one.
I apologize if I didn't put this constructor in the previous question, but I simply forgot about it. I was my mistake.
thanks for the help and sorry for wasting your time.

How to guard against function arguments being passed in the wrong order?

Say I have a C++ function that looks like this:
double myfunction(double a, double b) {
// do something
}
Which I then call like this:
double a = 1.0;
double b = 2.0;
double good_r = myfunction(a, b);
double bad_r = myfunction(b, a); // compiles fine
I would like to make sure that a and b are never provided in the wrong order.
What is the best way to ensure this in C++?
Other languages allow named parameters, like this:
double good_r = myfunction(a=a, b=b);
double bad_r = myfunction(a=b, b=a); // mistake immediately obvious
double bad_r = myfunction(b=b, a=a); // compiles fine
Or perhaps the problem can be partly solved using types, i.e.
double my_type_safe_function(a_type a, b_type b) {
// do something
}
a_type a = 1.0;
b_type b = 2.0;
double good_r = myfunction(a, b);
double bad_r = myfunction(b, a); // compilation error
EDIT: A couple of people have asked what I mean by the "wrong order." What I mean is that, in real code a and b have some significance. For example, the arguments might instead be height and width. The difference between them is very important for the function to return the correct result. However, they are both floats and they both have the same dimensions (i.e. a length). Also, there is no "obvious" order for them. The person writing the function declaration may assume (width, height) and the person using the function may assume (height, width). I would like a way to ensure this doesn't happen by mistake. With two parameters it is easy to be careful with the order, but in a large project and with up to 6 arguments mistakes creep in.
Ideally I would like the checks to be done at compile time, and for there to be no performance hit (i.e. at the end of the day they are treated as plain old floats or whatever).
How about this:
struct typeAB {float a; float b; };
double myfunction(typeAB p) {
// do something
return p.a - p.b;
}
int main()
{
typeAB param;
param.a = 1.0;
param.b = 2.0;
float result = myfunction(param);
return 0;
}
Of course, you can still mess up when you assign your parameter(s) but that risk is hard to avoid :)
A variant is to have one struct per "new" type, and then make them go away in optimized builds using macros.
Something along these lines (only slightly tested, so it could be way off):
#define SAFE 0
#if SAFE
#define NEWTYPE(name, type) \
struct name { \
type x; \
explicit name(type x_) : x(x_) {}\
operator type() const { return x; }\
}
#else
#define NEWTYPE(name, type) typedef type name
#endif
NEWTYPE(Width, double);
NEWTYPE(Height, double);
double area(Width w, Height h)
{
return w * h;
}
int main()
{
cout << area(Width(10), Height(20)) << endl;
// This line says 'Could not convert from Height to Width' in g++ if SAFE is on.
cout << area(Height(10), Width(20)) << endl;
}
I think you already provided the easiest solution, using types.
One alternative could be using a builder class and method chaining.
Like:
class MyfunctionBuilder {
MyFunctionBuilder & paramA(double value);
MyFunctionBuilder & paramB(double value);
double execute();
(...)
}
Which you would use like this:
double good_r = MyFunctionBuilder().paramA(a).paramB(b).execute();
But this is a lot of extra code to write!
What is the "wrong order" actually? In this example of yours
double myfunction(double a, double b) {
// do something
}
double a = 1.0;
double b = 2.0;
double good_r = myfunction(a, b);
double bad_r = myfunction(b, a);
how do you actually want to know if this is the right order? What if the variables would be named "quapr" and "moo" instead of "a" and "b"? Then it would be impossible to guess whether the order is right or wrong just by looking at them.
With this in mind, you can do at least two things. First, is to give meaningfull names to the arguments, e.g.
float getTax( float price, float taxPercentage )
instead of
float getTax( float a, float b )
Second, do the necessary checks inside:
float divide( float dividend, float divisor )
{
if( divisor == 0 )
{
throw "omg!";
}
}
It is possible to do more complex checks, such as making a functor, and setting it's parameters explicitly, but in most of the cases that just complicates things without much benefit.

Passing a 2D array of Structs by reference in C++

SO im pretty new to c++ and im trying to pass a 2D array of a struct type by reference to a function. As far as i know they are automatically passed by reference. Here is my code.The problem is probably obvious but i cant figure it out. The complier keeps saying variable or field "function" declared void and bArray was not declared in this scope.
void function(balloons bArray[][5]);
int main()
{
struct balloons
{
float totalWeight;
float largestBalloon;
};
balloons balloonsArray[20][5];
function(balloonsArray);
}
void function(balloons bArray[][5])
{
bArray[1][1].totalWeight = 1.0
bArray[1][1].largestBalloon = 1.0
}
You're defining your struct within main, other parts of your code need to use it also. Move the definition outside the function:
struct balloons
{
float totalWeight;
float largestBalloon;
};
void function(balloons bArray[][5]);
int main()
{
// ...
And you haven't terminated the two statements in your function, you'll need semicolons there:
bArray[1][1].totalWeight = 1.0;
bArray[1][1].largestBalloon = 1.0;

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.

Expected primary expression before '.'

#include <iostream>
using std::cout;
using std::endl;
class square {
public:
double length, width;
square(double length, double width);
square();
~square();
double perimeter();
};
double square::perimeter() {
return 2*square.length + 2*square.width;
}
int main() {
square sq(4.0, 4.0);
cout << sq.perimeter() << endl;
return 0;
}
I'm trying to write a simple class program. I am getting the error
in member function 'double square::perimeter()';
.cpp:21: error: expected primary-expression before '.' token
.cpp:21: error: expected primary-expression before '.' token
Does this mean I have to use 2*square::length + 2*square::width?
square is a type, not an object; instead of
return 2*square.length + 2*square.width;
do
return 2*length + 2*width;
(which is implicitly the same as:
return 2*this->length + 2*this->width;
which you may, or please may not, prefer for clarity).
2*square::length + 2*square::width would be valid syntax if length and width were
static members of square, or
members of some base class square, or
objects in some namespace square
Yes, the accurate form would be:
return 2*square::length + 2*square::width;
since square is a type, not an object.
In this context, it's the same as:
return 2*this->square::length + 2*this->square::width;
However, since it's the same object and the same type, you can just write:
return 2*this->length + 2*this->width;
or, most simply:
return 2*length + 2*width;
Simply use
double square::perimeter() {
return 2 * length + 2 * width;
}
double square::perimeter() {
return 2*square.length + 2*square.width;
}
You need to say square::perimeter() because you are defining a method of the square class itself. It may seem like you want to define it on a specific object, but you want it to be available to all instances of square, so you need to define it on a specific one.
The instance variables length and width on the other hand, pertain to a specific instance of a class and NOT the entire class itself (otherwise you would declare them as static). This means that you can just refer to them directly instead of going through the class itself, and the compiler will know what variables you're talking about. This is because width and length are defined in the same scope as the method, so you don't need to give it special directions with :: to tell it where to find what its looking for. Hence:
double square::perimeter() {
return 2 * length + 2 * width; //will refer to the instance variables automatically
}
to access instance variables, just name them:
double square::perimeter() {
return 2*length + 2*width;
}
double square::perimeter() {
return 2*square.length + 2*square.width;
}
what is the square in this function? square is a class. you use the . operator to acces members from objects. like sq.somefun();
so you perimeter function should be:
double square::perimeter() {
return (2*(length + width));
}
But isnt the length and width of square equal?