c++ reference field in a class throw the constructor - c++

I have this class:
typedef int ID;
typedef int Salary;
class Worker {
protected:
ID id;
Salary& salary;
public:
Worker();
Worker(ID Id, Salary Salary) {
this->id=Id;
this->salary=salary;
}
.
.
.
}
and this one:
class WSalary : public Worker {
public:
WSalary(ID Id, Salary& Salary) {
this->id=Id;
this->salary=Salary;
}
.
.
.
}
and I have this error in the constructor
uninitialized reference member 'Worker::salary' [-fpermissive]
I want to put in the WSalary class a field (called salary) that has the same address in the field "salary" in the class worker.. so when I change the salary in the worker class it would change automatically in the WSalary class.
whats the solution?
thanks

In your worker example you are trying to bind a value to a non-const reference. This would create a dangling reference and is not a good idea. Just store a value in the class instead of a reference or pass a reference as the constructor argument and use the initialization list.
In WSalary you need to use the initialization list:
WSalary(ID id, Salary& s) : id(id), salaray(s) {}
Or call the constructor of the base (should you fix it to accept a reference):
WSalary(ID id, Salary& s) : Worker(id, s) {}
In C++11 you also just re-use the Worker constructor in the derived class using this syntax:
using Worker::Worker;

Use initialisation list:
WSalary(ID Id, Salary& Salary) : id(Id), salary(Salary)
{
}
instead of
WSalary(ID Id, Salary& Salary) {
this->id=Id;
this->salary=Salary;
}

If the indirection is intentional, then use a pointer.
A reference cannot be made to refer to something else, once it's been initialized.
This means that a reference member generally prohibits assignment for the class, and that it cannot be initialized by assignment.
Pointers, in contrast, can be made to point elsewhere by assignment.

Related

C++ Declaring an inherited constructor?

I'm having difficulties in defining a constructor for a class that inherits the properties of another class
class Transportation {
public:
int ID;
string company;
string vehicleOperator;
Transportation(int,string,string) {
}
};
class SeaTransport: public Transportation {
public:
int portNumber;
SeaTransport(int)::Transportation(int,string,string) {
}
};
I'm having issues with line 18 (SeaTransport(int)::Transportation(int,string,string)).
The error I receive occurs at the pont where I declare Transportation.
As seen in the code, a class Transportation is the body class and class SeaTransport inherits the properies of Transportation.
Transportation::Transportation(int, std::string, std::string)
+2 overloads
type name is not allowed
This error occurs at the int
typedef std::__cxx11::basic_string std::string
type name is not allowed
and this final error occurs at both string variables.
It seems you mix together scoping and a constructor initializer list.
The double-colon operator :: is for scope, while a constructor followed by a single colon and a list of initializations is an initializer list.
You must declare the SeaTransport constructor to take all the arguments, including those for the parent class (assuming you want to pass them on to the base constructor):
SeaTransport(int port, int id, string company, string operator);
Then in the definition (implementation) of the constructor you "call" the parent constructor in the constructor initializer list:
SeaTransport(int port, int id, string company, string oper)
: Transport(id, company, oper), // "Call" the parent class constructor
portNumber(port) // Initialize the own members
{
}
As Mr Some Programmer Dude said, you've a Scope problem in your code,
I will try to answer for your second question which is, how to add featured variables on your constructor.
Same as what you did for the port attribute.
You can define before all your Attribute which is boatNumber as int boadNumber = 0 then, you'll overload your
constructor with boatNumber(num) after the initializer operator and int num before the initializer operator.
class Transportation {
public:
int ID;
string company;
string vehicleOperator;
Transportation(int,string,string) {
}
~Transportation(){}
};
class SeaTransport: public Transportation {
public:
int portNumber;
int boatNumber;
SeaTransport(int num, int port, int id, string company, string oper)
:Transportation(id, company, oper), boatNumber(num),portNumber(port) {}
~SeaTransport(){}
};
But, if you want to get things more specific, you can create another class which is derived from SeaTransport
And then you'll define the number of your boat and more other details, if you want.
I'll draw you an instance of it :
class Boat: public SeaTransport {
public:
int boatNumber;
Boat(int bNum,int num, int port, int id, string company, string oper):
SeaTransport( num, port, id, company, oper),boatNumber(bNum){}
~Boat(){}
};

Map error : a nonstatic member reference must be relative to a specific object

I have seen the solution of another problem like this one , but it doesn't help me at all. On the line
studMap[getName()].push_back(getGrade());
I get the following error :
A nonstatic member reference must be relative to a specific object.
This is my code:
class CStudent :public CPerson {
protected: CPerson::name;
protected: CPerson::EGN;
protected: string specialty;
public: CStudent(string n, string E, string s) {
setName(n);
setEgn(E);
setSpecialty(s);
}
string getName() {
return name;
}
};
class CSubject:public CStudent{
protected: string subj;
protected: int grade;
void setSubj(string s) {
subj = s;
}
void setGrade(int g) {
grade = g;
}
int getGrade() {
return grade;
}
std::map<CStudent, std::list<int> > studMap;
studMap[getName()].push_back(getGrade());
};
How can I pass my value from the method to the map without getting this error and where does it come from ?
studMap[getName()].push_back(getGrade());
Expressions like this must be inside a method.
You have written it inside a class declaration. In the class declaration, you can only declare/define methods and member data. If you expect that expression to be executed when an object of CStudent is created, you must write it inside the CStudent constructor.
Your statement should be part of some method. It's same error as if you tried to write statements in global scope, but current context confuses compiler which expects a declaration here.
You need create instance of the class in-order to use the properties of class. i.e. make instance of CSubject to use studMap. The error you're seeing says that 'Non-static functions have to be called through the objects'.

How is a constructor for a derived class supposed to be like in c++ when derived class has added data member

I am new to c++. I have been trying to get past this error. I know when a class in derived, it inherits everything from the base class, but what if the derived class has other data members? How is the constructor suppose to be?
When I try putting only the new I try to pass parameters to the newly made class members in the constructor I get an error to say it doesn't match that of the base class. When I try using that of the base class and adding the new data members it tells me I am redefining. So I wonder whats left to do to get past this error below is my code.
This is the base class:
class movielibrarybase
{
public:
movielibrarybase(string name, string dirname, string gen, int price);
void setname(string name);
string getname();
void setdirector_name(string dirname);
string getdirector_name();
void setgenre(string gen);
string getgenre();
void setprice(int price);
int getprice();
void display();
~movielibrarybase();
protected:
string name;
string director_name;
string genre;
int price;
};
And this is the derived class:
class songlibrary: public movielibrarybase
{
public:
songlibrary();
void setartist_name(string name);
string getartist_name();
void setsong_position(string position);
string getsong_position;
~songlibrary();
protected:
string artist_name;
string song_postion;
};
I am getting the following errors:
songlibrary.cpp||In constructor 'songlibrary::songlibrary(std::string, std::string, std::string, int, std::string, std::string)':|
songlibrary.cpp|6|error: no matching function for call to 'movielibrarybase::movielibrarybase()'|
movielibrarybase.cpp|3|note: candidates are: movielibrarybase::movielibrarybase(std::string, std::string, std::string, int)|
movielibrarybase.h|8|note: movielibrarybase::movielibrarybase(const movielibrarybase&)|
songlibrary.cpp|34|error: no 'std::string songlibrary::getsong_position()' member function declared in class 'songlibrary'|
For that case you use the member initializer list in the constructor to invoke the right constructor in the base class:
songlibrary::songlibrary(string name, string dirname, string gen, int price,
string artist_name, string song_position)
: movielibrarybase(name, dirname, gen, price), // initialize base class
artist_name(artist_name), // initialize member in this class
song_position(song_position) {
// other ctor stuff
}
If you do not state the parent class on that list, it will default to the default constructor. Since there is no default constructor in your movielibrarybase class, a compiler error occurred.
In your case it would be something like:-
songlibrary::songlibrary( string n, string director, string gen,
int pri, string artist, string song )
: movielibrarybase( n, director, gen, pri ),
artist_name( artist ), song_postion( song )
One thing to note here is sequence in member initializer list matters. First calls should be to base classes and then derived classes members should be initialized in the order in which they are declared in a class.
Also, class members are initialized in the order of their declaration in the class, the order in which they are listed in a member initialization list makes not a whit of difference

C++ inheritance getting error

I'm having a bit of trouble figuring out this error I have. So I have a Person class, and a Student subclass.
The Person class has the following constructor:
Person(const string &name)
{ this->name = name;
}
The Student class has the following constructor:
Student::Student(const string &name, int regNo)
{ this->name = name;
this->regNo = regNo;
}
When I try to compile the Student class though, I get this error for the constructor:
In constructor 'Student::Student(const string&, int)':
error: no matching function for call to 'Person::Person()'
I'm new to C++, so I have no idea why I get this error, but it has something to do with the inheritance of Person obviously.
You are attempting to call Person's default constructor, but it doesn't have one. In any case, it looks like what you want to do is call its single parameter constructor:
Student::Student(const string& name, int regNo) : Person(name), regNo(regNo)
{
}
Similarly, use the constructor initialization list in Person's consructor:
Person(const string& name) : name(name) {}
This way, you are initializing your data members to the desired value, instead of default initializing them and then assigning them new values.
You need to delegate to the correct ctor from the base class like this:
Student::Student(const string &name, int regNo)
: Person( name )
{
this->regNo = regNo;
}
Note that this uses initializer lists, so you could use the more idiomatic
Student::Student(const string &name, int regNo)
: Person( name ), regNo( regNo )
{
}
and for the Person ctor:
Person(const string &name)
: name( name )
{
}
The initializer list is used to initialize base classes and the member variables, everything you don't explicitly put in there is default constructed (and in your code, it is later assigned in the ctor's body). Since Person is not default constructible, you must initialize it in the initializer list.

Strange value returned from method on child object

I'm having a little bit of problem with my derived class. Basically I have a super class Object and a derived class UnmovableObject. I'm trying to add a boolean variable to the derive class, so that I can later on read it and see if my objects can be moved or not. The problem I have is that I'm storing all objects (super and derived) into a list<Object> inventory. Every time I read the values from the list, I get a weird value (204) for the isFixed() method. This is the code:
//super class
#pragma once
#include "stdafx.h"
class Object{
public:
Object(); //constructor
Object(const string name, const string description); //constructor
~Object(); //destructor
private:
string nameOfObject; //the name of the room
string objectDescription; //the description of the room
};
//derived class
#pragma once
#include "stdafx.h"
#include "object.h"
//This class creates unmovable objects - the user can't pick them up.
class UnmovableObject : public Object {
public:
UnmovableObject(string name, string description);
UnmovableObject(const Object &object) : Object(object){};
bool isFixed();
private:
bool fixed;
};
//the constructor of this class takes a boolean value (by default true) - the object is fixed in this room
UnmovableObject::UnmovableObject(string name, string description) : Object(name, description){
this->fixed = true;
}
//returns false as the object is not movable
bool UnmovableObject::isFixed(){
return this->fixed;
}
//other class
list<Object> inventory;
How can I use inventory.push_back(Object/UnmovableObject); so that when I try to access the inventory I could get the correct boolean value for all of them—true for the UnmovableObject; false for the Object .
The first problem is called slicing. Wen you store into a list of Object only the Object subobject of the derived type is being copied. The list will only contain Object. If you need polymorphic behavior you need to use (smart) pointers in the container, so that the objects don't get copied (only the pointers).
The second problem is that you cannot hope to obtain the value of a member attribute that does not exist in your type. That is, since Object does not have a fixed member, you cannot obtain its value.
If you are wanting to find out if any of the Objects are fixed, then you should really make isFixed() a member of the Object class. Then override it in the derived class. If you do it this way, you don't actually have to store the fixed variable. Also, you should change your vector to be a vector of pointers to Objects.
class Object
{
public:
Object(); //constructor
Object(const string name, const string description); //constructor
~Object(); //destructor
virtual bool isFixed() {return false;}
private:
string nameOfObject; //the name of the room
string objectDescription; //the description of the room
};
class UnmovableObject : public Object {
public:
UnmovableObject(string name, string description);
UnmovableObject(const Object &object) : Object(object){};
virtual bool isFixed() {return true;}
};
vector<Object*> myVector;