I get an error when try to call the function string SetToString(StringSet aSet); from an inherited class.
The header file for the base class:
#ifndef ITEM_H
#define ITEM_H
#include <ostream>
#include <set>
#include <string>
using namespace std;
typedef set<string> StringSet;
class Item
{
protected:
string title;
StringSet keywords;
public:
Item();
Item(const string& title, const string& keywords);
virtual ~Item();
void addKeywords(string keyword);
virtual ostream& print(ostream& out) const;
string getTitle() const;
string SetToString(StringSet aSet);
};
Implementation file for the base class :
#include "Item.h"
...
string Item::SetToString(StringSet aSet) {
string key;
int sizeCount = 0;
for (auto const& e : aSet) {
key += e;
sizeCount++;
if (sizeCount < aSet.size()) {
key += ", ";
}
}
SetToString(keywords);
return key;
}
...
When I try to do string k = SetToString(keywords); in the inherited class, I get the error : Error C2662 'std::string Item::SetToString(StringSet)': cannot convert 'this' pointer from 'const Book' to 'Item &'. How to fix this error, and why do I get it ?
Item::SetToString is not marked as const, so it cannot be called through a const pointer or reference, or on a const object.
You seem to be trying to call it from a function which is marked as const, and which therefore can't modify the current object (this) including by calling non-const functions on it.
Either make your inherited function not const, or make the base function const.
Related
I have been looking in different threads with this error which is quite common but it feels like the IDE I am using messed with my workspace and I can't quite find the problem. I am setting up an extremely basic class called "Movie" that is specified below:
Movie.hpp :
#ifndef MOVIE_HPP
#define MOVIE_HPP
#include <iostream>
#include <string>
using std::string, std::cout,std::size_t;
class Movie
{
private:
std::string name;
std::string rating;
int watched_ctr;
public:
Movie(const string& name, const string& rating, int watched_ctr);
~Movie();
//getters
string get_name() const;
string get_rating() const;
int get_watched() const;
//setters
void set_name(string name);
void set_rating(string rating);
void set_watched(int watched_ctr);
};
#endif // MOVIE_HPP
Movie.cpp:
#include <iostream>
#include <string>
#include "Movie.hpp"
using std::string, std::cout,std::size_t,std::endl;
Movie::Movie(const string& name, const string& rating, int watched_ctr)
: name(name) , rating(rating) , watched_ctr(watched_ctr) {
}
Movie::~Movie()
{
cout << "Destructor for Movies class called /n";
}
//Getters
string Movie::get_name(){return name;}
string Movie::get_rating(){return rating;}
string Movie::get_watched(){return watched_ctr;}
//Setters
void Movie::set_name(std::string n){this -> name = n;}
void Movie::set_rating(std::string rating){this -> rating = rating;}
void Movie::set_watched(int ctr){this -> watched_ctr = ctr;}
The main.cpp I am trying only consists in creating one Movie object:
#include <iostream>
#include <string>
#include "Movie.hpp"
using std::string, std::cout,std::size_t,std::endl;
int main()
{
Movie StarTrek("Star Trek", "G", 20);
}
As you can see, I set all the attribute to private in order to exercise with the set/get methods but I keep stumbling upon the same error on each of them stating >"C:/Users/.../ProjectsAndTests/MoviesClass/Movie.cpp:18:8: error: no declaration matches 'std::__cxx11::string Movie::get_name()"
if you could give me a hint on what might cause this error I would greatly appreciate thank you!
I tried opening another workspace with classes implemented inside of them and the syntax I am using is very close from this test workspace I opened which compiled fine (no error regarding declaration match).
There are 2 problems with your code.
First while defining the member functions outside class you're not using the const. So to solve this problem we must use const when defining the member function outside the class.
Second, the member function Movie::get_watched() is declared with the return type of string but while defining that member function you're using the return type int. To solve this, change the return type while defining the member function to match the return type in the declaration.
//----------------------vvvvv--------->added const
string Movie::get_name()const
{
return name;
}
string Movie::get_rating()const
{
return rating;
}
vvv------------------------------>changed return type to int
int Movie::get_watched()const
{
return watched_ctr;
}
Working demo
I have two classes: "Station" which has method getName() returning string and "Profit" which has the overloaded method sellAt(string stName), sellAt(Station st). To avoid duplicate code I call sellAt(string stName) in sellAt(string stName), however in some cases (see code example below) compiler gives an error: "no instance of overloaded function "Profit::SellAt" matches the argument list. Argument types are: (std::string)". Is it a bug or I miss something?
Station.h
#pragma once
#include <string>
using namespace std;
class Station
{
private:
string sName;
public:
Station(string name);
string getName();
};
Station.cpp
#include "Station.h"
Station::Station(string name)
:sName(name)
{}
string Station::getName()
{
return sName;
}
Profit.h
#pragma once
#include "Station.h"
#include <string>
class Profit
{
public:
double SellAt(string& stName);
double SellAt(Station& st);
};
Profit.cpp
#include "Profit.h"
double Profit::SellAt(const string& stName)
{
// do stuff
}
// Works as expected
double Profit::SellAt(Station& st)
{
string stName = st.getName();
return SellAt(stName);
}
// Compile error
double Profit::SellAt(Station& st)
{
return SellAt(st.getName());
}
// Compile error
double Profit::SellAt(Station& st)
{
double result = SellAt(st.getName());
return result;
}
Yksisarvinen answered in the comment below the original question:
st.getName() is a temporary. You cannot bind non-const reference to a temporary. I suppose you shouldn't want to modify stName in Profit::SellAt(), so change the type of argument to const std::string&.
Thanks for the help!
I'm trying to write a class, that stores configuration items with their name, a description and their types.
OptionItem.h:
#include <typeinfo>
#include <string>
class OptionItem {
public:
OptionItem(std::string name, std::string text, type_info type);
std::string name() const;
std::string text() const;
type_info OptionItem::type() const;
private:
std::string _name, _text;
type_info _type;
};
OptionItem.cpp:
OptionItem::OptionItem(std::string name, std::string text, type_info type) :
_name(name), _text(text), _type(type) {};
std::string OptionItem::name() const { return _name; }
std::string OptionItem::text() const { return _text; }
type_info OptionItem::type() const { return _type; }
I have a second class that holds the different options:
Opt.h:
#include "OptionItem.h"
struct Opt {
static const OptionItem opt1, opt2;
};
Opt.cpp:
#include "myOwnClass.h"
const OptionItem Opt::opt1= OptionItem("Option 1", "text1", typeid(std::string));
const OptionItem Opt::opt2= OptionItem("Option 2", "text2", typeid(myOwnClass));
A third class that held the actual settings of my program would then look like this:
Settings.h
#include "OptionItem"
#include <any>
#include <map>
#include <string>
class Settings {
public:
void setOption(OptionItem option, std::any value);
template<class T> T& getOption(const std::string &option) const;
private:
std::map<std::string, std::any> _options;
}
Settings.cpp
void Settings::setOption(OptionItem option, std::any value) {
_options.emplace(option.name(), value);
}
T& Settings::getOption(const std::string &option) const {
if (_options.find(option) == _options.end()) {
throw(std::runtime_error("No such option \"" + option + "\"
}
else {
return std::any_cast<T>(_options[option]);
}
}
A call to Settings::getOption might look like this:
getOption<Opt::opt1.type()>(Opt::opt1.name())
I know this has its problems (which is, why I'm asking :-) ) the first one being that std::type_info doesn't seem to be copyable. (the compiler(VIsualCPP) tells me 'type_info::type_info(const type_info &)': attempting to reference a deleted function). The other problem, of which I am sure there are plenty I don't know about since compilation stops with the aforementioned error.
Do you have any suggestions how I could make this work?
I am pretty new to c++ and have no idea why I am getting this error, except that I think it's to do with using the string type for getter methods.
The error message:
C:\Users\Robin Douglas\Desktop\week6>g++ -c Student.cpp
Student.cpp:15:31: error: no 'std::string Student::get_name()' member function d
eclared in class 'Student'
Student.cpp:20:43: error: no 'std::string Student::get_degree_programme()' membe
r function declared in class 'Student'
Student.cpp:25:32: error: no 'std::string Student::get_level()' member function
declared in class 'Student'
Student.hpp
#include <string>
class Student
{
public:
Student(std::string, std::string, std::string);
std::string get_name;
std::string get_degree_programme;
std::string get_level;
private:
std::string name;
std::string degree_programme;
std::string level;
};
Student.cpp
#include <string>
#include "Student.hpp"
Student::Student(std::string n, std::string d, std::string l)
{
name = n;
degree_programme = d;
level = l;
}
std::string Student::get_name()
{
return name;
}
std::string Student::get_degree_programme()
{
return degree_programme;
}
std::string Student::get_level()
{
return level;
}
The following code defines fields (variables) rather then methods.
public:
Student(std::string, std::string, std::string);
std::string get_name;
std::string get_degree_programme;
std::string get_level;
Then, when you implement it in the .cpp file the compiler complains that you try to implement a method that was not declared (since you declared get_name to be a variable).
std::string Student::get_name()
{
return name;
}
To fix, just change your code as below:
public:
Student(std::string, std::string, std::string);
std::string get_name();
std::string get_degree_programme();
std::string get_level();
I got two classes, one named Person that I checked is working (I can create objects of that class so the problem should not be here).
I then have another class called Family with composition from Person:
Family.h
#include "Person.h"
class Family
{
public:
Family();
void printFamily();
private:
Person dad_();
Person mum_();
Person son_();
Person daughter_();
};
Family.cpp
#include "Family.h"
Family::Family()
{
}
void printFamily()
{
dad_.printAll();
mum_.printAll();
son_.printAll();
daughter_.printAll();
//printAll() is a function in the Person class that worked when
//I tested it earlier with only the person class
}
But when i try to compile this I get an error:
left of '.printAll' must have class/struct/union
'son_' : undeclared identifier
This error goes for all the .printAll() calls in family.cpp.
I can't see why this wouldn't work, so I hope you can.
Edit1:
Ok i changed
void printFamily()
to
void Family::printFamily()
That removes one error, but i still get
left of '.printAll' must have class/struct/union
Edit2
Ah my bad with the Person calls i changed them to
Person dad_;
and the same with the rest.
Seems like their might be an error with my Person class so i will post that also
Person.h
#include <string>
using namespace std;
class Person
{
public:
Person( const string & = "000000-0000", const string & = "N", const string & = "",const string & = "N");
~Person();
void setFirstName(const string &);
void setMiddleName(const string &);
void setLastName(const string &);
void getData(string &,string &,string &,string &);
static int getNumberOfPersons();
void printPartially() const;
void printAll() const;
bool checkForSameName(const Person &);
private:
string firstName_;
string middleName_;
string lastName_;
string socialSecNumber_;
static int numberOfPersons_;
};
Person.cpp
#include "Person.h"
#include <iostream>
int Person::numberOfPersons_ = 0;
Person::Person( const string &sNumber, const string &firstName, const string &middleName,const string &lastName )
:firstName_(firstName),middleName_(middleName),lastName_(lastName),socialSecNumber_(sNumber)
{
numberOfPersons_ ++;
}
Person::~Person()
{
numberOfPersons_--;
}
void Person::setFirstName(const string &firstName)
{ firstName_ = firstName; }
void Person::setMiddleName(const string &middleName)
{ middleName_ = middleName; }
void Person::setLastName(const string &lastName)
{lastName_ = lastName;}
void Person::getData(string &fName,string &mName,string &lName,string &sNumber)
{
fName = firstName_;
mName = middleName_;
lName = lastName_;
sNumber = socialSecNumber_;
}
int Person::getNumberOfPersons()
{
return numberOfPersons_;
}
void Person::printPartially() const
{
cout <<"Navn: "<<firstName_<<" "<<middleName_<<" "<<lastName_<<endl;
cout <<"Født: ";
for (int i = 0;i<6;i++)
{
cout <<socialSecNumber_.at(i);
}
}
void Person::printAll() const
{
cout <<"Navn: "<<firstName_<<" "<<middleName_<<" "<<lastName_<<endl;
cout <<"Personnr: "<<socialSecNumber_<<endl;
}
bool Person::checkForSameName(const Person &p)
{
if (p.firstName_ == firstName_ && p.middleName_ ==middleName_ && p.lastName_ == lastName_)
return true;
else
return false;
}
Now i am getting some new errors:
error C2011: 'Person' : 'class' type redefinition
see declaration of 'Person'
'Family::dad_' uses undefined class 'Person'
The "dad" error applies to the whole family
You have a few syntax issues.
First, you're declaring each of what are supposed to be member variables as functions which return Person. They should look like (note, no parens):
Person dad_;
Person mum_;
Person son_;
Person daughter_;
You're also missing the scoping on your definition of printFamily:
void Family::printFamily() {
...
}
Without the preceding Family::, C++ thinks you're defining a free function, and doesn't know to look inside the Family class for the declarations of dad_, mum_, etc.
Additionally, at least with the code you've shown, there's no way to initialize the people in your class. The Family constructor should take arguments to define the people, or you should have setters which allow defining them later. Right now, you'll get 4 identical people, set up however the default person constructor builds them.
I would normally prefer the constructor method, but I have other design reservations about your code to begin with (e.g. Does a family always contain mum, dad, brother, sister?) and that's not really what this question is about.
The line:
Person dad_();
says that dad_ is a function that returns a Person, not an object. Did you mean that? Similarly for others.
Try
Person dad_;
Family.h
#include "Person.h"
class Family
{
public:
Family();
void printFamily();
private:
Person dad_;
Person mum_;
Person son_;
Person daughter_;
};
Family.cpp
#include "Family.h"
Family::Family()
{
}
void Family::printFamily()
{
dad_.printAll();
mum_.printAll();
son_.printAll();
daughter_.printAll();
//printAll() is a function in the Person class that worked when
//I tested it earlier with only the person class
}
The out of line definition of a member function needs to include the class name:
void Family::printFamily()
{
//...
Surprisingly, you already got this right for the constructor but then immediately forgot...
Second, your private class members are functions, not data members (which is odd), but if that's deliberate, you need to call them:
dad_().printAll();
// ^^^