I'm having some problems with inheritance and constructors in C++. What I've got is a class VirtualMotor which inherits Motor (is that the correct way to say it?). The class VirtualMotor should have it's own constructor, but I'm doing something wrong when I create it and the compiler gives me an error (se below). My source code is like this:
Motor.h
class Motor
{
protected:
float speed;
float angle;
public:
Motor();
float getSpeed();
float getAngle();
virtual void setSpeed( float speed );
virtual void setAngle( float angle );
Motor.cpp
#include "Motor.h"
float Motor::getSpeed() { return speed; }
float Motor::getAngle() { return angle; }
VirtualMotor.h
#include "Motor.h"
class VirtualMotor: public Motor
{
private:
float lastSpeed;
public:
VirtualMotor();
void setSpeed(float speed);
void setAngle(float angle);
};
VirtualMotor.cpp
#include "VirtualMotor.h"
VirtualMotor::VirtualMotor()
{
speed = 2;
angle = 5;
}
void VirtualMotor::setSpeed(float speed)
{
this->speed = speed;
}
void VirtualMotor::setAngle(float angle)
{
this->angle = angle;
}
Main.cpp
#include <iostream>
#include "VirtualMotor.h"
using namespace std;
int main (int argc, char **argv)
{
VirtualMotor m;
cout << m.getSpeed() << endl;
m.setSpeed(9);
cout << m.getSpeed() << endl;
return 0;
}
To compile I use the command g++ Main.cpp Motor.cpp VirtualMotor.cpp -o main and I get the following error:
/tmp/ccIdYJaR.o: In function `VirtualMotor::VirtualMotor()':
VirtualMotor.cpp:(.text+0x29): undefined reference to `Motor::Motor()'
/tmp/ccIdYJaR.o: In function `VirtualMotor::VirtualMotor()':
VirtualMotor.cpp:(.text+0x5d): undefined reference to `Motor::Motor()'
/tmp/ccIdYJaR.o:(.rodata._ZTI12VirtualMotor[typeinfo for VirtualMotor]+0x8): undefined reference to `typeinfo for Motor'
collect2: ld returned 1 exit status
I feel there's a really simple solution to this, but I just can't see it. I've tried to use VirtualMotor::VirtualMotor() : Motor::Motor() and other variations without any luck.
In your code you declare the Motor() constructor but never provide an implementation for it. Also, you don't seem to be using include guards in your header files. motor.h should look something like this (although this isn't to do with the problem you are asking about):
#ifndef INC_MOTOR_H
#define INC_MOTOR_H
class Motor
{
... // your stuff here
};
#endif
And lastly, protected data is generally a bad idea.
You've declared a default constructor for the class Motor in Motor.h (Motor(); immediately below public:), but you haven't given it a definition in Motor.cpp.
As the others mentioned, Motor()'s definition is missing. The easiest way would be to change its declaration to 'Motor() {}'. This way is cleaner, however:
class Motor {
protected:
Motor(float speed, float angle)
: speed(speed), angle(angle)
{}
public: .
}
...
VirtualMotor :: VirtualMotor
: Motor(2,5)
So you don't have to initialize base class members directly from within VirtualMotor's c'tor.
Add in motor.cpp
Motor::Motor(){
}
Related
When I have both the prototype and definition in the same header file (as shown below), and I create an object in main (source.cpp) with Cube c1{}; I get no error and the default constructor works; c1's side will be defaulted to 0.0
class Cube {
private:
double side;
static int counter;
//this is cube.h
public:
Cube(double s = 0.0) :side{ s } { //constructor
counter++;
}
};
However, when I separate the interface from the implementation like this:
class Cube {
private:
double side;
static int counter; //static data
//this is cube.h
public:
Cube(double);
};
Its implementation:
#include <iostream>
#include "Cube.h"
int Cube::counter{ 0 };
//this is cube.cpp
Cube::Cube(double s = 0.0) :side{ s } {
counter++;
}
And I go to the main function in source.cpp, Cube c1{}; now gives me the error:
no instance of constructor "Cube::Cube" matches the argument list
Note: When I gave c1 a value, like Cube c1{5}; it works in both cases.
You should put the default argument to the declaration Cube(double = 0.0);, not the definition. Otherwise the matching function cannot be found in other files.
I am trying to simulate some plasma physics and for that I decided to create my "Simulation world" as a class, defined in "World.h" file:
#ifndef _WORLD_H
#define _WORLD_H
class World{
public:
World(int _Nx, double _x0, double _xf); //Constructor prototype
int _Nx; //Number of nodes
double _dx; //Cell width
void setTime(double _dt, int _num_ts);
protected:
double _x0; //System origin
double _xf; //System ending
double _dt = 0; //time step length
int _num_ts; //number of time steps
};
#endif
The implementation of the class prototypes goes:
#include "World.h"
World::World(int Nx, double x0, double xf)
{
this->_Nx = Nx;
this->_x0 = x0;
this->_xf = xf;
this->_dx = (xf - x0)/(Nx - 1);
//std::cout << Nx;
}
void World::setTime(double dt, int num_ts)
{
this->_dt=dt;
this->_num_ts=num_ts;
}
The problem I am having is that when I call the function "World::setTime(/**/)" from main:
int main()
{
//Create computational system
World world(1000, 0.0, 0.1); //(Nx, x0, xm)
World::setTime(world._dx, 10000);
/*CODE*/
return 0;
}
the compiler shows the message:
[Error] cannot call member function 'void World::setTime(double, int)' without object
Referring to the value of 'int num_ts' given as an argument. What is the prblem? What is the object it is referring to?
I was reading this post:
cannot call member function without object
but I cannot apply the solution in there because I wrote down a constructor in my class. Thank you for your replies!
I think that the problem is that you are calling member function of a defined class instead of an object. To fix that, I would try putting:
World world(1000,0.0,0.1); //(Nx,x0,xm)
world.setTime(world._dx, 10000);
This way you are calling an object that you have defined as "world" of type World.
I am new to c++ and am stuck on the syntax of declaring classes.
From what I have gathered you should store all declarations in a header file, I'll call it declarations.h;
#pragma once
void incptr(int* value);
void incref(int& value);
class Player
{
public:
int x, y;
int speed;
void Move(int xa, int ya)
{
x += xa * speed;
y += ya * speed;
}
void printinfo()
{
std::cout << x << y << speed << std::endl;
}
};
Now Player is a class which I want to store in a cpp file called functions.cpp
I want to move the above Player class into the below file functions.cpp
#include "common.h"
void incptr(int* value)
{
(*value)++;
}
void incref(int& value)
{
value++;
}
common.h contains;
#pragma once
#include <iostream>
#include <string>
#include "declarations.h"
What I think is happening is when i write the Player class in the header file, its being declared in that file, well, already there. If i move the Player class into functions.cpp I need to leave a declaration. I'm not sure what the compiler expects as a declaration when it comes to classes.
I have tried;
class Player();
functions::Player();
void Player::Move(int xa, int ya);
Also a few other variations but these make the most sense to me.
Sorry if this is a bit messy, still trying to get a hold on the language. Thanks in advance for you help!
Edit: Sorry I missed the main function;
#include "common.h"
int main()
{
Player player = Player();
player.x = 5;
player.y = 6;
player.speed = 2;
player.Move(5, 5);
player.printinfo();
std::cin.get();
}
A declaration for a class is just as simple as
class Player; // Note there are no parentheses here.
This form is most commonly used when you have circular dependencies between two classes. It is more common to define a class in a header file but put the definitions of member functions in a .cpp file. For your purposes a we can make a header file named player.h:
class Player
{
public:
int x, y;
int speed;
void Move(int xa, int ya);
void printinfo();
};
Note that this declaration does not contain the bodies of the member functions because these are really definitions. You can then put the function definitions in another file. Call it player.cpp:
void Player::Move(int xa, int ya)
{
x += xa * speed;
y += ya * speed;
}
void Player::printinfo()
{
std::cout << x << y << speed << std::endl;
}
Note how we have to now specify that each of these functions is a member of the Player class with the Player:: syntax.
Now assuming you also have a main.cpp file with your main() function, you can compile your code like this:
g++ main.cpp player.cpp
For this simple example, you will be fine defining your functions inside of the class declaration. Note that this makes the functions "inline" which is another topic that you should read about.
So I am trying to forward declare a class in my C++ project and then create it in main.
So I have player_obj.cpp which contains the class, classes.h which forward declares the class, and main.cpp which uses it.
classes.h
#ifndef CLASSES_H
#define CLASSES_H
class player_class
{
public:
int x;
int y;
char sprite;
int xprevious;
int yprevious;
private:
bool active;
public:
void update_xy();
player_class(int _x, int _y, char _sprite);
void step();
void destroy();
};
#endif
main.cpp
#include <iostream>
#include "classes.h"
using namespace std;
int main()
{
player_class player_obj (5,5,'#');
cout << player_obj.x << ", " << player_obj.y << endl;
return 0;
}
and player_obj.cpp
#include <iostream>
#include <Windows.h>
using namespace std;
class player_class
{
public:
//Coordinates
int x;
int y;
//Sprite
char sprite;
//Previous coordinates
int xprevious;
int yprevious;
//Not everyone can set the activity
private:
//Active
bool active;
//Update xprevious and yprevious - Called by the step event
void update_xy()
{
xprevious = x;
yprevious = y;
}
//All functions public
public:
//Create event/Constructer
player_class(int _x, int _y, char _sprite)
{
//Set default variables
x = _x;
y = _y;
sprite = _sprite;
xprevious = x;
yprevious = y;
active = true;
}
//Step event
void step()
{
//Update old xprevious and yprevious
update_xy();
//Do other stuff here
}
//Drestroy event
void destroy()
{
active = false;
}
};
I thought that would work out all right but when I compile and run it I get:
main.cpp:(.text+0x2c): undefined reference to`player_class::player_class(int, int, char)'
I've done some research, but I can't seem to fix this issue.
I greatly appreciate any help!
Well you're sort of close, what you have in your header is indeed a class declaration (not a forward declaration mind you).
The problem is you never defined it. What you have in player_obj.cpp is an abomination of class redefinition, but you already have your class declared. Just include the header file and define the functions one by one and you're done!
#include "classes.h"
player_class::player_class(int _x, int _y, char _sprite)
{
//Set default variables
x = _x;
y = _y;
sprite = _sprite;
xprevious = x;
yprevious = y;
active = true;
}
// and so on
If you're serious about learning modern C++ though, a few notes:
#pragma once is the modern way of guarding header files. Don't use those #ifdef..#endif constructs.
generally speaking, don't name anything starting with underscores. Especially not parameters visible as part of your public contract.
you have class initializers for a reason, use them! You don't need half a screen of copy pasting variables in your constructors.
You dont want a forward declaration. You want a declaration. It is a classical case of declaring a class in a header file and defining its functions in a cpp file. Then including the header where-ever you want to use your class
You only need forward declarations when you want to use a pointer to that class as a parameter to a function or a member variable somewhere but the definition of that class is not available yet.
Note that when you forward declare a class, you cannot use this class's member variables or functions in that header
-regards
Gautam
I have edited previous post to give more complete question so:
I have a class named Heliostat that in the header file i want to make 5 objects.3 of them are from class vector and 2 of them from class targets.The vector class constructors needs as operators Target objects or vector objects. I get error that the program does not recognise the operators as any type. I will give you the code.
I work for an arduino project inside eclipse.
This is the heliostat class header:
#ifndef HELIOSTAT_H_
#define HELIOSTAT_H_
#include "Target.h"
#include "TargetCatalog.h"
#include "vector.h"
#include "Sun.h"
class Heliostat {
private:
public:
double Pitch;
double Azimuth;
Target heliostat(4501472.0,662766.0,1.0);
Target reactor(4501474.0,662768.0,30.0);
Vector sunsVec(Sun::getPitch1year(),Sun::getAzimuth1yearArcsin());
Vector reactVec(heliostat,reactor);
Vector normalVec(reactVec,sunsVec);
Heliostat();
virtual ~Heliostat();
};
#endif /* HELIOSTAT_H_ */
It will have some functions that are not writen know.
The cpp has almost nothing only the constructor that is empty.
The Target class header:
#ifndef TARGET_H_
#define TARGET_H_
class Target {
private:
public:
enum targetlist{Helio,React,Normalpoint};
double gpsX;
double gpsY;
double gpsZ;
Target(double gpsEast, double gpsNorth, double gpsAlt);
virtual ~Target();
};
#endif /* TARGET_H_ */
The vectors class header:
#ifndef VECTOR_H_
#define VECTOR_H_
#include "Target.h"
class Vector {
public:
double easting;
double northing;
double altitude;
Vector(Target startTarget,Target endTarget);
Vector(double targetsPitch,double targetsAzimuth);
Vector(Vector reactorVector,Vector sunVector);
double calculateInclinationAngle(Vector reactorVector,Vector sunVector);
double getPitch(Vector helioNormalVec);
double getAzimuth(Vector helioNormalVec);
virtual ~Vector();
};
#endif /* VECTOR_H_ */
and the vector.cpp:
#include "vector.h"
#include "Maths.h"
#include "Target.h"
//vector::vector() {
// // TODO Auto-generated constructor stub
//
//}
vector::vector(Target startTarget, Target endTarget) {
double eastingTemp=endTarget.gpsX-startTarget.gpsX;
double northingTemp=endTarget.gpsY-startTarget.gpsY;
double altitudeTemp=endTarget.gpsZ-startTarget.gpsZ;
double vecMagnitude=sqrt(pow(eastingTemp,2)+pow(northingTemp,2)+pow(altitudeTemp,2));
easting=eastingTemp/vecMagnitude;
northing=northingTemp/vecMagnitude;
altitude=altitudeTemp/vecMagnitude;
}
vector::vector(double targetsPitch, double targetsAzimuth) {
easting=Maths::cosDeg(targetsPitch)*Maths::sinDeg(targetsAzimuth);
northing=Maths::cosDeg(targetsPitch)*Maths::cosDeg(targetsAzimuth);
altitude=Maths::sinDeg(targetsPitch);
}
vector::vector(vector normReactorVec, vector normSunVec) {
double inclinationAngle=calculateInclinationAngle(normReactorVec,normSunVec);
double normalMagnitude=2*Maths::cosDeg(inclinationAngle);
easting=(normReactorVec.easting+normSunVec.easting)/normalMagnitude;
northing=(normReactorVec.northing+normSunVec.northing)/normalMagnitude;
altitude=(normReactorVec.altitude+normSunVec.altitude)/normalMagnitude;
}
double vector::calculateInclinationAngle(vector reactorVector,vector sunVector) {
double angleResult=(reactorVector.easting*sunVector.easting)
+ (reactorVector.northing*sunVector.northing)
+ (reactorVector.altitude*reactorVector.altitude);
double inclinationAngleDoubled=Maths::arccos(angleResult);
double inclinationAngle=inclinationAngleDoubled/2.0;
return inclinationAngle;
}
double vector::getPitch(vector helioNormalVec) {
double pitch=Maths::arcsin(helioNormalVec.altitude);
if (pitch<0){
pitch=0;
Serial.println(F("error on pitch calc"));
}
return pitch;
}
double vector::getAzimuth(vector helioNormalVec) {
double pitch=getPitch(helioNormalVec);
double theta=Maths::arcsin(helioNormalVec.easting/Maths::cosDeg(pitch));
//taking absolute of theta function abs() get only int as operators
if (theta<0){
theta=-theta;
}
double azimuth;
if (helioNormalVec.easting>0){
if(helioNormalVec.northing>0){
azimuth=theta;
}else if(helioNormalVec.northing<0){
azimuth=180-theta;
}else{
azimuth=90;
}
}else if(helioNormalVec.easting<0){
if(helioNormalVec.northing>0){
azimuth=360-theta;
}else if(helioNormalVec.northing<0){
azimuth=180+theta;
}else{
azimuth=270;
}
}else{
if(helioNormalVec.northing>0){
azimuth=0;
}else if(helioNormalVec.northing<0){
azimuth=180;
}else{
Serial.println(F("error on Azimuth calc"));
}
}
return azimuth;
}
vector::~vector() {
// TODO Auto-generated destructor stub
}
About sun class i just use 2 functions that return doubles.
At this poing there is no sketch i do not expect the program to do something i am verifing it for syntax error.
The error i get says that:
'Sun::getPitch1year' is not a type
The same goes for: getAzimuth1yearArcsin(),TargetCatalog::rectorTarget,TargetCatalog::heliostatTarget,reactVec,sunsVec.
For the first lines at the heliostat header.
Target heliostat(4501472.0,662766.0,1.0);
Target reactor(4501474.0,662768.0,30.0);
i get syntax error that says:expected ',' or '...' before numeric constant
is there any solution about these problems?
In heiliostat.h, the line
Vector sunsVec(Sun::getPitch1year(),Sun::getAzimuth1yearArcsin());
declares a function named sunsVec and should declare what types it takes. The current code tries to call two functions.
Replace Sun::getPitch1year() with the type that function returns, and do the same for Sun::getAzimuth1yearArcsin())