C++ access a derived class method using a base class pointer - c++

I am trying to access the get_workhour() function. How do I do this?
Does polymorphism only works for overriden functions?
The manager class has a special function get_workhour() which is not present in base class employee. How can we call that function when both class's objects are stored in a vector of employee type, using polymorphism?
#include <iostream>
#include <vector>
using namespace std;
class employee{
protected:
string name;
double pay;
public:
employee(){
name="xyz";
pay =0.0;
}
employee(string name,double pay) {
this->name = name;
this->pay = pay;
}
string get_name(){
return name;
}
virtual double get_pay(){
return pay;
}
};
class manager:public employee{
protected:
int workhour;
public:
manager(){
workhour = 0;
}
manager(string name,double pay,int workhour):
employee(name,pay){
this->workhour = workhour;
}
virtual int get_workhour(){
return workhour;
}
virtual double get_pay() {
return pay + 100;
}
};
int main()
{
employee emp1("vivek",1500);
manager m1("william",1300,10);
vector<employee*> emps;
emps.push_back(&m1);
emps.push_back(&emp1);
cout<<"Name of manager is : "<<emps[0]->get_name()<<endl;
cout<<"Pay for the manager is :"<<emps[0]->get_pay()<<endl;
cout<<"Workhour of manager is : "<<ptr->get_workhour()<<endl;
cout<<"Name of employee is : "<<emps[1]->get_name()<<endl;
cout<<"Pay for the employee is : "<<emps[1]->get_pay()<<endl;
return 0;
}

You can't and you shouldn't. If you want all Derived to be interacted with via Base's interface, then everything you want to do to a Derived must be represented by Base's interface.

In general C++ (and most object oriented languages) try to discourage downcasting (casting a base type to a derived type). If you absolutely need to you can use a dynamic_cast to cast an employee to a manager. But do this only if you are sure that your pointer actually refers to a manager. Without a cast you only have access to the base type's interface.
You can use the dynamic_cast as follows:
manager* m = dynamic_cast<manager*>(emps[0]);

One option is to have an empty method for get_workhour() in the base class and just have the manager class override it.

Related

Inheritence in c++

#include<iostream.h>
#include<conio.h>
#include<stdio.h>
class person {
private: char name[50];
int age;
public: void get_name() {
cout<<"Enter name"<<endl;
gets(name);
}
void put_name() {
cout<<"Name : ";
puts(name);
cout<<endl;
}
void get_age() {
cout<<"Enter age"<<endl;
cin>>age;
}
void put_age() {
cout<<"Age : "<<age<<endl;
}
};
class student : public person {
private : int roll;
public : void get_roll() {
cout<<"Enter roll"<<endl;
cin>>roll;
}
void put_roll() {
cout<<"Roll : "<<roll<<endl;
}
};
int main() {
student A;
A.get_name();
A.get_roll();
A.get_age();
A.put_name();
A.put_age();
A.put_roll();
getch();
clrscr();
return 0;
}
There are following queries:
If private members of class person are not inherited in class student then how can an instance of class student store values in them?
Shouldn't the variables just not exist in the class student?
Note: I am using old compiler for a college project.
If a Student wants to access the Person fields, the simplest way is make them protected, so they can be accessed by all derived class of Person.
Another way is use public getter/setter methods (you can even set them protected, but at this point is better use protected fields), in this way all classes can see and set the fields of Person.
Indeed, even if a variable is declared private in the base class, it exist in the derived class ( a Student is in any case a Person, so the field in Person must be initialized) but it can't be reached by her.
A is an object of type Student and it can access protected or public member function and data member of class Person. Now answer to your query, you are trying to use the function of class Person using object of class Student which is possible (as inherited publicly) and since the function and those private data member are part of same class (Person), so those function can use the variable.
Note : private, public and protected member have no effect within same class.

no matching function for call to employee::employee()

I am trying the derived class example from TCPL.
Manager is kind of employee with additional info of level. I kept getting the error:
no matching function for call to employee::employee()
in the constructor of manager::manager()
All members of employee are public and accessible. What is wrong with the manager constructor?
#include <iostream>
#include <string>
using namespace std;
class employee{
public:
enum type {M,E};
type hier;
string id;
employee(string idd):hier(E){id=idd;};
};
class manager: public employee{
public:
int level;
manager(string idd, int lv){hier=employee::M; id=idd;level=lv;};
};
void print(employee *x){
if(x->hier == employee::E){
cout<<"I am employee with id "<<x->id<<endl;
}
else{
cout<<"I am manager with id "<<x->id<<endl;
manager* y=static_cast<manager *>(x);
cout<<"My level is "<<y->level<<endl;
}
}
int main(){
employee t("334");
manager u("223", 2);
print(&t);
print(&u);
}
Second version
The previous version was bad in terms of encapsulation
This is the new version
#include <iostream>
using namespace std;
enum type {M, E};
class employee{
string id;
type hier;
public:
employee(string idd, type hi=E):hier(hi),id(idd){}
string whatid(){return id;}
type whattype(){return hier;}
};
class manager: public employee{
int level;
public:
manager(string idd, int lv):employee(idd,M),level(lv){}
int whatlv(){return level;}
};
Instead of directly accessing the private member of employee and manager, I made members private and use a function to access them.
#include <iostream>
#include <string>
#include "manager_employee.h"
using namespace std;
void print(employee *x){
if(x->whattype() == E){
cout<<"I am employee with id "<<x->whatid()<<endl;
}
else{
cout<<"I am manager with id "<<x->whatid()<<endl;
manager *y=(manager *)x;
// manager* y=static_cast<manager *>(x);
cout<<"My level is "<<y->whatlv()<<endl;
}
}
int main(){
employee t("334", E);
manager u("223", 2);
print(&t);
print(&u);
}
By declaring a constructor in employee, you remove its default constructor; so you can't create one without specifying the ID.
This means that any derived classes will need to provide the ID to the base-class constructor:
manager(string idd, int lv) : employee(idd) {hier=employee::M; level=lv;}
// ^^^^^^^^^^^^^
For consistency, you might like to initialise level in the initialiser list rather than the constructor body; and it might make more sense to initialise hier to the correct value via another parameter in the employee constructor, rather than giving it a default value then overwriting it:
employee(string idd, type hier = E) : hier(hier), id(idd) {}
manager(string idd, int lv) : employee(idd, M), level(lv) {}
If you have any explicit constructor for a class, the default constructor goes out of existence.
So for that reason, when you initialize an object of the derived class, it tries to initialize the base class members as well. And as you have not given a constructor taking no arguments, this error is thrown.
Either define a default constructor for employee or try calling the base class constructor as:
manager(string idd, int lv):employee(idd){//your code}
Manager constructor should call base class ctor in its initialization list:
manager(string idd, int lv) : employee(idd) {hier=employee::M; id=idd;level=lv;}
Also consider using initlization list for other members in your classes.

Memory sharing; Inheritance; Base and Derived instances; C++

Ok, this example is pretty straight-forward for the concept I'm trying to understand. I'll just show you the code:
class Base
{
protected:
string name;
public:
virtual string getName() const { return this->name; }
virtual void setName(string name) { this->name = name; }
....
}
class Derived : public Base
{
private:
double price;
....
}
main(int argc, char** argv)
{
Base* base = new Base("Base Class");
Derived* derived = new Derived(base, 453.21);
derived->setName("Name changed!");
cout << "Name of instance: " << base->getName() << endl;
// Desired effect
Output: 'Name changed!'
// Actual effect
Output: 'Base Class'
....
}
The issue for me is this. I want to create an instance of derived class with reference to already created instance of base class, so when I change any member variable of base class trough the derived instance, I can see the change on previously created base instance in the way demonstrated above.
Note: I hope that you will manage to comprehend what I meant, as I am aware that my terminology is probably little off. Please, don't be harsh. :)
Note: I won't be showing / writing constructors, since I am not sure what is the best way to do this, if even any exists and the syntax may be incorrect.
This seems to indicate the problem:
Base* base = new Base("Base Class");
Derived* derived = new Derived(base, 453.21);
as it is usually not necessary to construct the Base class separatly. Your derived class will already contain a Base instance implicitly, you don't have to add a pointer to one manually and set it from the ctor. I don't know how your ctor looks, but it should look like this:
Derived(const std::string& name, double p) : Base(name), price( p ) {}
If this enough to fix it yourself, good, otherwise post all the code of your example. Instead of the two lines from your code that I quoted above, it should look more like:
Derived* derived = new Derived("Base Class", 453.21);
If you post the code of Derived, it should be obvious for us and it will be much easier to explain it to you on your concrete example.
The way you are trying to do is weird, but you can simply use inheritance concept like this code:
class Base
{
public:
Base(const string &name) : name(name) {}
virtual void setName(const string &name) { this->name = name; }
virtual string getName() const { return name; }
protected:
string name;
};
class Derived : public Base
{
public:
Derived(const string &name, double price) : Base(name), price(price) {}
private:
double price;
};
int main()
{
Derived* derived = new Derived("Base Class", 453.21);
derived->setName("Name changed!");
Base *base = derived;
cout << "Name of instance: " << base->getName() << endl;
}
Output
Name of instance: Name changed!
You don't need a create Base object and pass it to the derived object.
Instead, create a derived object and pass its address to a Base pointer.

How to implement Inheritance in C++ and resolve the error "parent class is not accessible base of child class"?

I am new to C++. I like to explore the idea of Inheritance in C++. Whenever I try to compile the following code I get the error:
for C++ includes, or <iostream> instead of the deprecated header <iostream.h>. To disable this warning use -Wno-deprecated.
D:\C Practice Files\Vehicle.cpp: In function `int main()':
D:\C Practice Files\Vehicle.cpp:26: error: `void Vehicle::setStationary_state(bool)' is inaccessible
D:\C Practice Files\Vehicle.cpp:141: error: within this context
D:\C Practice Files\Vehicle.cpp:141: error: `Vehicle' is not an accessible base of `Ship'
Execution terminated
Here is my code:
#include <iostream.h>
#include <conio.h>
using std::string;
class Vehicle{
private:
bool stationary_state;
double max_speed;
double min_speed;
double weight;
double volume;
int expected_life;
string fuel_type;
string model;
string year_of_manufacture;
public:
Vehicle(){
}
void setStationary_state(bool m){
stationary_state = m;
}
bool getStationary_state(){
return stationary_state;
}
};
class Bike:Vehicle{
private:
string bike_type;
public:
void setBike_Type(string t){
type = t;
}
string getBike_Type(){
return bike_type;
}
};
class Aircraft:Vehicle{
private:
short no_of_wings;
public:
void setNo_of_wings(short wings)
{
no_of_wings = wings;
}
short getNo_of_wings()
{
return no_of_wings;
}
};
class Car:Vehicle{
private:
string reg_no;
string type;
public:
void setType(string t)
{
if ((t=="Pneumatic") || (t=="Hydraulic"))
{
type = t;
}
else
{
cout<<"\nInvalid entry. Please enter the correct type:";
setType(t);
}
}
};
class Ship:Vehicle{
private:
bool has_radar_detection;
public:
void setRadar_Detection(bool r){
has_radar_detection = r;
}
bool getRadar_Detection(){
return has_radar_detection;
}
};
int x;
main()
{
Vehicle v;
Bike b;
Car c;
Aircraft a;
Ship s;
s.setStationary_state(true);
c.setType("xyz");
/*v.setStationary_state(true);
if (!(v.getStationary_state()))
{
cout<<"Vehicle is moving";
}
else
{
cout<<"Vehicle is at rest";
}
*/
getch();
}
What is really wrong there? What is the cause of the error and how to avoid it. Please explain in detail.
class has private default inheritance, so you would need to specify public, i.e.
class Ship : public Vehicle { }:
ans so on. struct has public inheritance as default.
You need to specify inheritance access level:
class Bike : public Vehicle
I.e. you need to make Vehicle a public base.
If you don't specify an access specifier, inheritance is automatically private.
You need to change these line:
class Ship:Vehicle
to this:
class Ship:public Vehicle
encapsulation is attained by placing related data in the same place and offering security to the data.include
private - access granted to same class
public - any code can access the data
protected - access granted to methods of the same class,friend class and derived class

Accessing derived class members with a base class pointer

I am making a simple console game in C++
I would like to know if I can access members from the 'entPlayer' class while using a pointer that is pointing to the base class ( 'Entity' ):
class Entity {
public:
void setId(int id) { Id = id; }
int getId() { return Id; }
protected:
int Id;
};
class entPlayer : public Entity {
string Name;
public:
void setName(string name) { Name = name; }
string getName() { return Name; }
};
Entity *createEntity(string Type) {
Entity *Ent = NULL;
if (Type == "player") {
Ent = new entPlayer;
}
return Ent;
}
void main() {
Entity *ply = createEntity("player");
ply->setName("Test");
ply->setId(1);
cout << ply->getName() << endl;
cout << ply->getId() << endl;
delete ply;
}
How would I be able to call ply->setName etc?
OR
If it's not possible that way, what would be a better way?
It is possible by using a cast. If you know for a fact that the base class pointer points to an object of the derived class, you can use static_cast:
Entity* e = /* a pointer to an entPlayer object */;
entPlayer* p = static_cast<entPlayer*>(e);
p->setName("Test");
If you don't know for sure, then you need to use dynamic_cast and test the result to see that it is not null. Note that you can only use dynamic_cast if the base class has at least one virtual function. An example:
Entity* e = /* a pointer to some entity */;
entPlayer* p = dynamic_cast<entPlayer*>(e);
if (p)
{
p->setName("Test");
}
That said, it would be far better to encapsulate your class's functionality using polymorphism (i.e. virtual functions).
Speaking of virtual functions, your class hierarchy as implement has undefined behavior: you can only delete an object of a derived type through a pointer to one of its base classes if the base class as a virtual destructor. So, you need to add a virtual destructor to the base class.
I would consider doing something like this:
public:
void setId(int id)
{
Id = id;
}
void virtual setName( string name ) = 0; // Virtual Function
string virtual getName() = 0; // Virtual Function
int getId() { return Id; }
protected:
int Id;
};
class entPlayer : public Entity {
string Name;
public:
entPlayer() {
Name = "";
Id = 0;
}
void entPlayer::setName(string name) { // Must define function
Name = name;
}
string entPlayer::getName() { return Name; } // again must define function here
};
You can do a dynamic cast:
entPlayer * pPlayer = dynamic_cast<entPlayer *>(pointer_to_base);
This will (if successful) result in a derived pointer.
Otherwise NULL is returned.
C++ makes what you are trying to do really awkward, because this is probably not what you should be doing, and it is trying to lead you to good object-oriented design. In fact, by default, compilers often disable run-time type information (RTTI), which is needed to make dynamic_cast work.
Without knowing your broader context, it's hard to say what you should do instead. What I can say is that if you wanted a more specific pointer, you should have put a ring on it you almost certainly shouldn't use a function that returns an Entity*, and there is probably a better approach.