I am having an issue with the class inheritance in my code. Here is what I am doing: I have two classes, one called Employee and the second called Manager. Employee is the base class, it has a function that prints Business card, containing the name of the company and the function name(), that prints the name of the employee. Class Manager is a derived class and inherits (public: Employee). When I try to print the same business card for the manager, it does not display the name, only the company name. What could be the problem?
Below is the little snippet of, first, the Employee class:
class Employee {
public:
// Constructor
Employee(const char* name, double salary) : _name(name), _salary(salary) {}
Employee() : _name(" "), _salary(0) {} // default constructor
// Accessors
const char* name() const { return _name.c_str() ; }
double salary() const { return _salary ; }
// Modifyers (if needed)
double set_salary( double salary) {
_salary = salary;
return _salary;
}
// Print functions
void businessCard(ostream& os = cout) const {
os << " +------------------+ " << endl
<< " | ACME Corporation | " << endl
<< " +------------------+ " << endl
<< " " << name() << endl ;
}
private:
string _name ;
double _salary ;
} ;
and, secondly, the Manager class:
class Manager : public Employee {
public:
// Constructors
Manager(const char* name, double salary, set<Employee*>& subordinates) :
_name(name), _salary(salary), _subs(subordinates) {}
...
// Accessors
const char* name() const {
string name;
name += _name;
name += " (Manager)";
return name.c_str() ;
}
void businessCard(ostream& os = cout) const {
Employee::businessCard();
}
private:
string _name ;
double _salary ;
} ;
The problem, as I think, is in the name() function, because if I write it explicitly, it appears on the card, though it is not inherited.
Could anyone help?
When you call Employee::businessCard(); it will call const char* name() const { return _name.c_str() ; } of Employee class. But earlier during the construction of the Manager object, you haven't passed name to the base class Employee, so it's not set in Employee class and you got it empty while printing.
So to make it work, it should be something like
Manager(const char* name, double salary, set<Employee*>& subordinates) : Employee(name,salary), _subs(subordinates)
and remove _name and _salary member variables from manager as it defeats the purpose of inheritance in this example.
Related
I am having some trouble with an unexpected output in the following simple code. The output works fine with the base class but I run into trouble with the derived class for some reason.
#include <iostream>
#include <string>
using namespace std;
class vehicle {
public:
string* name;
vehicle() {}
vehicle(const string& inputName) {name = new string(inputName);} //constructor
virtual ~vehicle() {delete name; name = nullptr;} // always make base class destructor virtual
//vehicle(const vehicle& rhs) {*this = rhs; cout << "copy called" << endl;} //copy constructor
vehicle& operator=(const vehicle& rhs) {
cout << "assignment called" << endl;
if(this == &rhs){
return *this;
}
name = new string(*rhs.name);
return *this;
} //assignment operator
virtual string& getName() const {return *name; cout << "base" << endl;} //mark function const if we are not going to make any changes to the object
};
class car : public vehicle {
string *title = new string;
public:
car() : vehicle() {}
car(const string& inputName) : vehicle(inputName) {*title = inputName;}
virtual ~car() {}
virtual string& getName() const {string temp = *title; return temp; cout << "derived" << endl;}
};
int main() {
car test("honda");
string temp;
temp = test.getName();
cout << temp;
return 0;
}
I am intending to get the following output:
honda
But am getting:
~weird square boxes~
Edit:
What i'm really trying to accomplish is something like the following in the derived class:
virtual string& getName() const {return "Car: " + *name;}
Before I get enflamed for using the heap for the string, please know that I am only experimenting here. It is my understanding that this should, in theory, work.
This function
virtual string& getName() const {string temp = *title; return temp; cout << "derived" << endl;}
invokes undefined behavior because it returns a reference to a local object temp that will not be alive after exiting the function.
You could define the function like
virtual const string& getName() const {return *name;}
and
const string& getName() const override { return *title;}
And the statements after return statements do not have an effect.
Also other your code has drawbacks. For example the copy assignment operator produces a memory leak.
Or you need explicitly to define the destructor for the class car.
Pay attention to that there is no sense to declare data members name and title as pointers to objects of the type std::string. Instead declare data members of the type std::string.
I'm writing some code to show inheritance.
In doing so, i want to illustrate it by having a base class that contains a vector of pointers that can hold object pointers of the derived class.
I'm getting this error that the "Child class is undeclared" in the base function "void addChild(string nm, string sm)" in the Parents class (base class). I do understand that it maybe out of scope in the base class.
Can someone provide me with a solution to this where i can still be able to instantiate an object of the derived class from within the base class.
I want to have everything done within the base class.
Please clarify if this is ok and is a good practice. If not, please suggest some ideas.
Here's my code:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Parents // base class
{
vector <Parents*> fam;
protected:
string firstName;
string lastName;
public:
Parents()
{
//default constructor
}
Parents(string fn, string ln)
{
firstName = fn;
lastName = ln;
}
void displayChildren()
{
if (fam.empty())
{
cout << "Vector is empty" << endl;
}
else
{
for (unsigned int i = 0; i < fam.size(); i++)
{
std::cout, fam.at(i);
}
}
}
void displayParentsInfo(Parents& const par)
{
cout << "First name : " << par.firstName << endl;
cout << "Last name : " << par.lastName << endl;
}
void addChild(string nm, string sm)
{
Child* c1 = new Child(nm, sm);
fam.push_back(c1);
}
};
class Child : public Parents //derived class
{
string firstname;
string surname;
public:
Child()
{
//default constructor
}
Child(string a, string b)
{
firstname = a;
surname = b;
}
//~Child()
//{
//destructor called
//}
void displayChildInfo(Child & const c)
{
cout << "Child's firstname : " << c.firstname;
cout << "Child's surname : " << c.surname;
}
};
Cheers!
Just move the definition of the function out of the definition of the class:
class Parents // base class
{
...
void addChild(string nm, string sm);
};
class Child : public Parents //derived class
{
...
};
void Parents::addChild(string nm, string sm)
{
Parents* c1 = new Child(nm, sm);
fam.push_back(c1);
}
As for good practice, it might be better to have a non-member function that prepares the Child and returns a pointer to it, and add something like:
void Parents::addToFam(Parents* c1)
{
fam.push_back(c1);
}
I am trying to store values of different types in one list. Now I am using #sbi's solution in this post. So I have base class:
class Variable
{
protected :
std::string name;
public :
Variable ( std::string name ) : name( name ) { }
virtual ~Variable () { }
virtual Print() const = 0;
};
And class that derives from it
template<typename T>
class TypedVariable : public Variable
{
protected :
const T* value;
public :
TypedVariable ( TString name, const T* value )
: Variable( name ),
value( value ) { };
T Value() { return *value; }
void Print() const
{
std::cout << "name: " << name << "\n";
std::cout << "value: " << *value << "\n";
}
};
And then I store Variables, for example in std::array
std::array<Variable*, size> myArray;
The problem is I cannot access value in this case because it is inside TypedVariable not Variable. My question is how do I access that field, if possible.
I am new to C++. Can someone please let me know what is wrong with the following code segment -
class Person {
public:
const std::string& name;
Person(const std::string& s): name(s) {}
void dump(void) const {
cout << name << endl;
//cout << &name << endl;
}
};
std::map<std::string, std::shared_ptr<Person>> plist;
std::string namestr = "Hoo";
std::shared_ptr<Person> r1(std::make_shared<Person>("Dull"));
plist.insert({"Key1", r1});
auto u = plist.find("Key1");
shared_ptr<Person> v = u->second;
v->dump();
plist.erase(plist.find("Key1"));
My intention is to create a database of Person objects and I was trying to use shared_ptr for that.
v->dump() causes a segmentation fault. However, if I use the 'namestr' variable instead of the string literal "Dull" then the v->dump() appears to work correctly, i.e. the following -
std::shared_ptr<Person> r1(std::make_shared<Person>(namestr));
Also, the following way also seems to work even though I use a string literal in the intializer.
std::shared_ptr<Person> r1(new Person("Dull"));
Pointers to the mistake I am making would be much appreciated!
class Person {
public:
const std::string& name;
Person(const std::string& s): name(s) {}
void dump(void) const {
cout << name << endl;
//cout << &name << endl;
}
};
this is storing a reference to a string whose life time is not guaranteed. You should do
class Person {
public:
const std::string name;
Person(const std::string& s): name(s) {}
void dump(void) const {
cout << name << endl;
//cout << &name << endl;
}
};
You code fails because "Dull" created a temporary string that went out of scope immediately
I have a question about building a method :
virtual std::string getPerson() const;
I have a child class Player and a the parent is Person.
Class Player :
class Player : public Person {
public:
Player(const std::string& p_name,const std::string& p_lastname, const int& p_age, const std::string& p_position);
virtual ~Player();
virtual Person* clone() const;
std::string getPosition() const;
virtual std::string getPerson() const;
private:
std::string m_position;
};
Class Person :
class Person {
public:
Person(const std::string& p_name,const std::string& p_lastname, const int& p_age);
virtual ~Person();
virtual std::string getPerson() const;
std::string getName() const;
std::string getLastName() const;
int getAge() const;
private:
std::string m_name;
std::string m_lastname;
int m_age;
};
When I try to add this in Player :
std::string Player::getPerson()
{
ostringstream os;
os << "Name :" << getName() << "\n";
os << "LastName :" << getLastName()() << "\n";
os << "Age :" << getAge()() << "\n";
os << "Position :" << getPosition();
return os.str();
}
I get Member declaration not found
I can't get it to work I would need to print something like this :
Name : John
Lastname : Smith
Age : 22
Position : Goalie
You missed the const at the end of the function signature. This should work:
std::string Player::getPerson() const
{
ostringstream os;
os << "Name :" << getName() << "\n";
os << "LastName :" << getLastName()() << "\n";
os << "Age :" << getAge()() << "\n";
os << "Position :" << getPosition();
return os.str();
}
But please mind what I said in the comment and change the function's name, or even better, make your class work with std::ostream by means of overloading operator<<.
Simple thing:
std::string getPerson() const;
is not the same as:
std::string getPerson();
If you can use c++11 use the override keyword, that protects you from such kind of mistakes. In your case the compiler detects the problem. But if you have other variants you maybe declare a new method instead of overloading!