I am currently working on a project that reads postcodes from a .csv file, completes a haversine calculation and stores items in a list based on a returned search radius. The postcode variables are defined via a class and uses an interface to impliment in main.cpp
The method that has thrown this all out of place is the operator < overload to provide alphabetical sorting of the postcodes (to be used to sort the list in main.cpp)
Postcode class;
#ifndef POSTCODE_H_
#define POSTCODE_H_
#include <stdexcept> // std::out_of_range
#include "IPostCode.h"
#include <string>
class PostCode : public IPostCode {
private:
int Id;
std::string Postcode;
std::string firstTwoChars;
double Lattitude;
double Longitude;
double distanceFromCentre;
public:
PostCode();
int getId() override;
std::string getPostcode() override;
std::string getFirstTwoChars() override;
double getLattitude() override;
double getLongitude() override;
double getdistanceFromCentre() override;
bool operator<(const PostCode& right) const override;
void setId(std::string newId) override;
void setPostcode(std::string newPostcode) override;
void setLattitude(std::string newLattitude) override;
void setLongitude(std::string newLongitude) override;
void setdistanceFromCentre(double newdistanceFromCentre) override;
void clearPostCode() override;
};
PostCode::PostCode() {
this->Id = 0;
this->Postcode = "";
this->Lattitude = 0.0f;
this->Longitude = 0.0f;
}
int PostCode::getId()
{
return this->Id;
}
std::string PostCode::getPostcode()
{
return this->Postcode;
}
std::string PostCode::getFirstTwoChars()
{
firstTwoChars = Postcode.substr(0, 2);
return this->firstTwoChars;
}
double PostCode::getLattitude()
{
return this->Lattitude;
}
double PostCode::getLongitude()
{
return this->Longitude;
}
double PostCode::getdistanceFromCentre()
{
return this->distanceFromCentre;
}
void PostCode::setId(std::string newId)
{
this->Id = std::stoi(newId);
}
void PostCode::setPostcode(std::string newPostcode)
{
this->Postcode = newPostcode;
}
void PostCode::setLattitude(std::string newLattitude)
{
this->Lattitude = std::stod(newLattitude);
}
void PostCode::setLongitude(std::string newLongitude)
{
this->Longitude = std::stod(newLongitude);
}
void PostCode::setdistanceFromCentre(double newdistanceFromCentre)
{
this->distanceFromCentre = newdistanceFromCentre;
}
void PostCode::clearPostCode() {
this->Id = 0;
this->Postcode = "";
this->Lattitude = 0.0f;
this->Longitude = 0.0f;
}
bool PostCode::operator<(const PostCode& right) const
{
return (Postcode.compare(right.Postcode) < 0);
}
#endif
Interface code;
#ifndef IPOSTCODE_H_
#define IPOSTCODE_H_
#include <string>
class IPostCode {
public:
virtual int getId() = 0;
virtual std::string getPostcode() = 0;
virtual double getLattitude() = 0;
virtual double getLongitude() = 0;
virtual double getdistanceFromCentre() = 0;
virtual std::string getFirstTwoChars() = 0;
virtual bool operator<(const PostCode& right) const = 0;
virtual void setId(std::string newId) = 0;
virtual void setPostcode(std::string newPostcode) = 0;
virtual void setLattitude(std::string newLattitude) = 0;
virtual void setLongitude(std::string newLongitude) = 0;
virtual void setdistanceFromCentre(double newdistanceFromCentre) = 0;
virtual void clearPostCode() = 0;
};
#endif
Errors.
1. Error C2259 'PostCode': cannot instantiate abstract class (This error is for the main.cpp declaration of a PostCode)
2. Error C3668 'PostCode::operator <': method with override specifier 'override' did not override any base class methods (Error within the postcode class)
3. Error C4430 missing type specifier - int assumed. Note: C++ does not support default-int
4. Error C2143 syntax error: missing ',' before '&' (3 + 4 = Errors within the interface)
I've read that the interface errors are due to type identifiers and i should declare them as static but this presents more error's. I am under the assumption that all methods within the interface are to be overridden as they declared pure virtual methods. (i.e = 0;). This isn't a void method because it returns values when implimented.
This does not resolve all the compiler warnings and errors; only the operator<.
Remove the operator< declaration from class IPostCode:
class IPostCode
{
public:
//--------------------------------------------------------
// Remove the function below
//--------------------------------------------------------
virtual bool operator<(const PostCode& right) const = 0;
};
Remove the override keyword from the PostCode class:
class PostCode : public IPostCode
{
public:
//---------------------------------------------------
// Remove "override" from the declaration below.
//---------------------------------------------------
bool operator<(const PostCode& right) const override;
};
You really don't want to override comparison operators or implement comparison functions in base classes. When you have a pointer of the base class type, you don't know what kind of child class it really points to. You could be comparing two different child classes.
Related
I am coding in stm32. Basically, I want to access a bool array data from another library. This is a header file of AP_Tmxk_LIDARScanner library stored data in scan.isObstacle which is a bool array. Also I made a return function named getObstacle(). Another library named AP_Tmxk_VFH to access data from getObstacle(). Is that ok? Or which is the way to copy that array in AP_Tmxk_VFH. Thanks for your help.
AP_Tmxk_LIDARScanner
class AP_Tmxk_LIDARScanner {
private:
struct{
bool isObstacle[180] = {}; //1: unsafe; 0:safe
bool available = false;
}scan;
public:
AP_Tmxk_LIDARScanner();
void init();
void update();
bool getAvailable() const{
return scan.available;
}
bool getObstacle() const{
return scan.isObstacle;
}
};
AP_Tmxk_VFH.h
class AP_Tmxk_VFH {
private:
struct{
bool Certain_Value[180] = {};
}sector;
const AP_Tmxk_LIDARScanner &_lidarscanner;
public:
// Constructor
AP_Tmxk_VFH(const AP_Tmxk_LIDARScanner &_lidarscanner);
void init();
void update();
};
AP_Tmxk_VFH.cpp
AP_Tmxk_VFH::AP_Tmxk_VFH(const AP_Tmxk_LIDARScanner &lidarscanner) :
_lidarscanner(lidarscanner)
{}
void AP_Tmxk_VFH::update()
{
if(_lidarscanner.getAvailable()){
sector.Certain_Value = _lidarscanner.getObstacle()
}
}
Here I modfiy my code format.
AP_Tmxk_LIDARScanner.h
class AP_Tmxk_LIDARScanner {
private:
struct{
bool isObstacle[180]= {}; //1: unsafe; 0:safe
bool available = false;
}scan;
public:
AP_Tmxk_LIDARScanner();
void init();
void update();
bool getAvailable() const{
return scan.available;
}
void getObstacle(int (&array)[180]);
};
AP_Tmxk_LIDARScanner.cpp
void AP_Tmxk_LIDARScanner::getObstacle(int (&array)[180])
{
for(int i=0; i<180; i++){
if(scan.isObstacle[i]){
array[i] = (array[i]+1 >= 5) ? 5 : array[i]+1;
}
else{
array[i] = (array[i]-1 >= 0) ? array[i]-1 : 0;
}
}
}
AP_Tmxk_VFH.h
class AP_Tmxk_VFH {
private:
struct{
int Certain_Value[180] = {};
}sector;
class AP_Tmxk_LIDARScanner &_lidarscanner;
public:
// Constructor
AP_Tmxk_VFH(class AP_Tmxk_LIDARScanner &_lidarscanner);
void init();
void update();
};
AP_Tmxk_VFH.cpp
AP_Tmxk_VFH::AP_Tmxk_VFH(class AP_Tmxk_LIDARScanner &lidarscanner) :
_lidarscanner(lidarscanner)
{}
void AP_Tmxk_VFH::update()
{
if(_lidarscanner.getAvailable()){
_lidarscanner.getObstacle(sector.Certain_Value);
}
}
I get a compile error "cannot convert 'Chips' to 'GroceryItem' and I'm having trouble figuring out how to actually convert something to a virtual class object. Teacher provided a 'GroceryCart' class that adds GroceryItems to the cart in 'main' and prints the cart out.
class GroceryItem {
public:
virtual ~GroceryItem();
virtual float GetPrice() = 0;
virtual char* GetDescription() = 0;
virtual float GetWeight() = 0;
};
#include "GroceryItem.h"
class Chips : public GroceryItem {
public:
Chips();
~Chips();
float GetPrice();
char* GetDescription();
float GetWeight();
private:
float price;
char* itemName;
float weight;
};
#include "GroceryItem.h"
#include "Chips.h"
Chips::Chips() {
price = 0.75;
itemName = new char[5];
itemName = "Chips";
weight = 1.0;
}
Chips::~Chips() {
delete this;
}
float Chips::GetPrice() {
return price;
}
char* Chips::GetDescription() {
return itemName;
}
float Chips::GetWeight() {
return weight;
}
int main(int argc, const char * argv[])
{
GroceryCart c;
c.AddItemToCart(new Chips);
std::cout << c;
return 0;
}
void GroceryCart::AddItemToCart(GroceryItem *i)
{
items.push_back(i);
}
provide full error log, check that container parameterized with pointer to GroceryItem (<GroceryItem*>)
As someone pointed out
delete[] itemName; //destructor
but you also have to define non-trivial copy-constructor/operator=, so it's better to replace char* with std::string, also need defined destructor for base abstract class even it's pure virtual.
This is some classes of my C++ program.
ElementTerrain.h:
#ifndef ELEMENTTERRAIN_H_
#define ELEMENTTERRAIN_H_
#include <iostream>
#include <string>
using namespace std;
class ElementTerrain {
public:
virtual ~ElementTerrain(){}
virtual string getElement() const = 0;
virtual string getType() const = 0;
virtual int getStock() const = 0;
};
#endif /* ELEMENTTERRAIN_H_ */
Mine.h:
#ifndef MINE_H_
#define MINE_H_
#include "ElementTerrain.h"
using namespace std;
class Mine : public ElementTerrain{
public:
Mine();
Mine(bool, bool, int);
Mine(const Mine &);
virtual ~Mine();
string getElement(){
return "Mine";
}
string getType(){
if(this->ur == true){
return "UR";}
if(this->plu == true){
return "PLU";}
return "None";
}
int getStock() {
return stock;
}
void setStock(int stock) {
this->stock = stock;
}
bool isUr() {
return ur;
}
bool isPlu() {
return plu;
}
private :
bool ur;
bool plu;
int stock;
};
#endif /* MINE_H_ */
Mine.cpp:
#include "Mine.h"
using namespace std;
Mine::Mine() {
this->ur = false;
this->plu = false;
this->stock = 0;
}
Mine::Mine(bool ur, bool plu, int stock){
this->ur=ur;
this->plu=plu;
this->stock = stock;
}
Mine::Mine(const Mine &m){
this->ur=m.ur;
this->plu=m.plu;
this->stock = m.stock;
}
Mine::~Mine() {
// TODO Auto-generated destructor stub
}
And this is the file where I'm having errors:
#include "ElementRobot.h"
#include "Mine.h"
#include <iostream>
using namespace std;
bool ElementRobot::RecolteMine(Terrain& t, ElementRobot& r) {
if(t.plateau[x][y]->getElem() != NULL){
if(t.plateau[x][y]->getElem()->getElement() == "Mine"){
Mine *m = new Mine();
if(m.getType() == r.getType() && m.getStock()>0 && r.stock<r.cap){
m.setStock(m.getStock()-1);
t.plateau[x][y]->setElem((Mine) t.plateau[x][y]->getElem());
return true;
}
if(m.getType() == r.getType() && m.getStock()==0){
cout << "Les stocks de cette mine sont épuisés.\n" << endl;
}
if(r.stock==r.cap){
cout << "Votre robot ne peut pas porter plus de minerai.\n" << endl;
}
if(m.getType() != r.getType()){
cout << "Ce robot n'est pas adapté à cette mine.\n" << endl;
}
}}
return false;
}
I want to create an object of type Mine with the copy constructor (here I tried just with the default constructor) but it say that I cannot allocate an object of abstract type Mine, even though in my class Mine there is no pure virtual method. I'm beginner with C++ and I don't understand my mistake. I couldn't find anything on the Internet either.
The signatures of the Mine's member functions do not match those of the base class (missing const qualifiers). Therefore, you have not overridden, but overloaded them and Mine continues to be abstract and not instantiable.
It's practically like having this:
class Mine {
public:
// this has to be implemented by deriving classes
virtual string getElement() const = 0;
// this is a separate overload
string getElement() { ... };
};
Solution: Fix the signatures:
string getElement() const { ... }
// ^^^^^
and so on...
C++11's override keyword would help you greatly - it would point out that there's no non-const qualified virtual member function named getElement to override.
You forgot const in function declarations.
Look here:
class ElementTerrain {
public:
virtual ~ElementTerrain(){}
virtual string getElement() const = 0; // <- notice 'const'
virtual string getType() const = 0; // <- notice 'const'
virtual int getStock() const = 0; // <- notice 'const'
};
So add const keyword to getElement,getType and getStock functions.
class Mine : public ElementTerrain{
public:
Mine();
Mine(bool, bool, int);
Mine(const Mine &);
virtual ~Mine();
string getElement() const{ // notice 'const' is added here..
return "Mine";
}
string getType() const{ // notice 'const' is added here..
if(this->ur == true){
return "UR";}
if(this->plu == true){
return "PLU";}
return "None";
}
int getStock() const{ // notice 'const' is added here..
return stock;
}
void setStock(int stock) {
this->stock = stock;
}
bool isUr() {
return ur;
}
bool isPlu() {
return plu;
}
private :
bool ur;
bool plu;
int stock;
};
Also if you want to get rid if this error forever I advice you to add override C++11 keyword after function declaration if you want to override functions like this:
int getStock() const override{
return stock;
}
In this case your C++ compiler will check if such a virtual function exists in any superclass and will raise a compilation error if it doesn't exist.
I have the following classes:
EuropeanOption.h
#pragma once
class OptionPricer;
class EuropeanOption
{
protected:
double dividend;
double strike;
double vol;
double maturity;
double spot;
public:
EuropeanOption(void);
virtual ~EuropeanOption(void);
virtual double price(double rate, const OptionPricer& optionPricer) const = 0;
virtual short getSign() const =0;
double getDividend() const;
double getStrike() const;
double getVol () const;
double getMaturity() const;
double getSpot() const;
void setDividend(double dividend_);
void setStrike(double strike_);
void setVol(double vol_);
void setMaturity(double maturity_);
void setSpot(double spot_);
};
EuropeanOption.cpp
#include "OptionPricer.h"
#include "EuropeanOption.h"
EuropeanOption::EuropeanOption(void)
{
}
EuropeanOption::~EuropeanOption(void)
{
}
double EuropeanOption::getDividend() const
{
return dividend;
}
double EuropeanOption::getMaturity() const
{
return maturity;
}
double EuropeanOption::getStrike() const
{
return strike;
}
double EuropeanOption::getSpot() const
{
return spot;
}
double EuropeanOption::getVol() const
{
return vol;
}
void EuropeanOption::setDividend(double dividend_)
{
dividend = dividend_;
}
void EuropeanOption::setMaturity(double maturity_)
{
maturity = maturity_;
}
void EuropeanOption::setSpot(double spot_)
{
spot = spot_;
}
void EuropeanOption::setVol(double vol_)
{
vol = vol_;
}
void EuropeanOption::setStrike(double strike_)
{
strike = strike_;
}
EuropeanCall.h
#pragma once
#include "EuropeanOption.h"
class EuropeanCall :
public EuropeanOption
{
public:
EuropeanCall(void);
EuropeanCall(double spot_, double strike_, double maturity_, double vol_, double dividend_ = 0);
~EuropeanCall(void);
short getSign() const;
double price(const OptionPricer& optionPricer, double rate) const;
}
;
EuropeanCall.cpp
#include "EuropeanCall.h"
#include "OptionPricer.h"
#include <cstdlib>
EuropeanCall::EuropeanCall(void)
{
}
EuropeanCall::EuropeanCall(double spot_, double strike_, double maturity_, double vol_, double dividend_)
{
spot = spot_;
strike = strike_;
maturity = maturity_;
vol = vol_;
dividend = dividend_;
}
EuropeanCall::~EuropeanCall(void)
{
}
short EuropeanCall::getSign() const
{
return 1;
}
double EuropeanCall::price(const OptionPricer& optionPricer, double rate) const
{
return optionPricer.computePrice(*this, rate);
}
OptionPricer.h
#pragma once
#include "EuropeanOption.h"
class OptionPricer
{
public:
OptionPricer(void);
virtual double computePrice(const EuropeanOption& option, double rate) const =0;
virtual ~OptionPricer(void);
};
OptionPricer.cpp
#include "OptionPricer.h"
OptionPricer::OptionPricer(void)
{
}
OptionPricer::~OptionPricer(void)
{
}
In my main function, when trying to instanciate an EuropeanCall like this:
EuropeanCall myCall(spot,strike,maturity,vol);
I get this error message:
object of abstract class type "EuropeanCall" is not allowed
I don't understand why the compiler considers EuropeanCall as an abstract class. Some help please?
You declared:
virtual double price(double rate, const OptionPricer& optionPricer) const = 0;
in your base class but got the parameters the wrong way round in your derived class:
double price(const OptionPricer& optionPricer, double rate) const;
This is not considered an override.
If some member function vf is declared as virtual in a class Base, and
some class Derived, which is derived, directly or indirectly, from
Base, has a declaration for member function with the same
name
parameter type list (but not the return type)
cv-qualifiers
ref-qualifiers
Then this function in the class Derived is also virtual (whether or
not the keyword virtual is used in its declaration) and overrides
Base::vf (whether or not the word override is used in its
declaration).
Since C++11 you can use the override specifier to ensure that a function is indeed virtual and is overriding a virtual function from the base class.
struct A
{
virtual void foo();
void bar();
};
struct B : A
{
void foo() const override; // Error: B::foo does not override A::foo
// (signature mismatch)
void foo() override; // OK: B::foo overrides A::foo
void bar() override; // Error: A::bar is not virtual
};
The function
virtual double price(double rate, const OptionPricer& optionPricer) const = 0;
Is pure virtual function, thus the classes are abstract. You cannot instantiate on instance of a class with a pure virtual function.
Your attempted override does not match this function signature;
double price(const OptionPricer& optionPricer, double rate) const;
The order of the parameters matter. To catch issues such as this, you can use the override specifier and the compiler will check that the function is overriding.
double price(const OptionPricer& optionPricer, double rate) const override;
// The override above will cause a compiler error.
I have the following code:
class STFDataPoint {
public:
virtual ImagePoint get_patch_top_left() const = 0;
virtual ImagePoint get_patch_bottom_right() const = 0;
virtual std::string get_image_filename() const = 0;
virtual ~STFDataPoint() = 0;
};
inline STFDataPoint::~STFDataPoint() {}
class TrainingDataPoint : public STFDataPoint{
private:
int row;
int col;
std::string class_label;
ImagePoint patch_top_left;
ImagePoint patch_bottom_right;
std::string image_filename;
public:
TrainingDataPoint(int row, int col, std::string class_label,
const ImagePoint & top_left,
const ImagePoint & bottom_right,
std::string image_filename);
std::string get_class_label() const;
inline bool operator==(const TrainingDataPoint& other) const{
return other.class_label == this->class_label;
}
inline bool operator!=(const TrainingDataPoint& other) const{
return !(*this == other);
}
virtual ImagePoint get_patch_top_left() const;
virtual ImagePoint get_patch_bottom_right() const;
virtual std::string get_image_filename() const;
};
And I am trying to run the following:
bool do_something(vector<STFDataPoint>& data_point){
return true;
}
int main(int argc, char* argv[]) {
ImagePoint left = ImagePoint(2,3);
ImagePoint right = ImagePoint(2,3);
TrainingDataPoint a = TrainingDataPoint(1,2,"",left, right, "");
vector<TrainingDataPoint> b;
b.push_back(a);
do_something(b);
}
But get the following error:
invalid initialization of reference of type ‘std::vector<STFDataPoint>&’ from expression of type `std::vector<TrainingDataPoint>`
however if I change the signature of do_something() to take in a STFDataPoint (not a vector of them) it runs fine. Can some one please explain why this is and also if there is a work around?
Thanks
Since vector<TrainingDataPoint> is not a subtype of vector<STFDataPoint> you cannot do this. Vectors are not covariant in parameter type.
However you can template do_something to make it work:
template <typename T>
bool do_something(vector<T>& data_point){
//common actions like
ImagePoint leftPatch = data_point[0].get_patch_top_left();
return true;
}
The type vector<TrainingDataPoint> is not the same as vector<STFDataPoint> and there is no conversion between the two. vector<A> is not a base type of vector<B>, even if A is a base of B.
What could work is to have a container of pointers or smart pointers to the base type, and change the function to use that:
bool do_something(vector<std::unique_ptr<STFDataPoint>>& data_point){
return true;
}
std::vector<std::unique_ptr<STFDataPoint>> b;
b.push_back( std::unique_ptr<STFDataPoint>(new TrainingDataPoint(1,2,"",left, right, "") ); // fill with any derived types of STFDataPoint
do_something(b);