English is not my first language. I hope I will not make lot of mistakes. I'll try my best to be as clear as possible!
I have a base class
class engine
{
private :
std::string name;
double weight;
public:
engine();
~engine();
std::string getName() const;
int getWeight() const
};
std::string engine::getName() const{
return this->name;
}
int engine::getWeight() const{
return this->weight;
}
and derived class
class diesel : public engine
{
private:
std::string name;
double weight;
public:
diesel();
~diesel();
};
diesel::diesel(){
this->name = Diesel;
this->weight = 500.00;
}
In my main.cpp
int main()
{
diesel diesel_engine;
const engine &e = diesel_engine;
std::cout<<e.getWeight()<<e.getName()<<std::endl;
return 0;
}
1- I must construct a diesel class named diesel_engine.
2- pass diesel_engine's value to a new engine by reference??
When I call const engine &e = diesel_engine;, diesel_engine's value(name and weight) should be copied to the new engine e.
So 'e' should have weight of 500.00 and the name "Diesel".
I don't get how can I use polymorphism to do that.
Thank you for reading this question!
Lets start with the class declarations
class Engine
{
private:
float weight_;
std::string name_;
public:
Engine(float weight, std::string name) : weight_(weight), name_(name){};
std::string GetName() const { return name_;}
};
class Diesel : public Engine
{
public:
Diesel(float weight, std::string name) : Engine(weight, name){}
};
So what we have here is an Engine class which is our base class and then we define our Diesel class, Diesel inherits from Engine and passes the arguments to its base class.
Now to use this:
Diesel disel_engine(0.0, "diesel engine");
const Engine& eng = disel_engine;
cout << eng.GetName();
The call to eng.GetName() prints the correct engine name
Demo Here
Related
I have the classes Player and HumanPlayer. HumanPlayer is derived from Player.
class Player {
private:
int id;
protected:
string name;
public:
Player(int id);
~Player();
}
class HumanPlayer : public Player {
public:
HumanPlayer(int id, string name);
}
I want to make a constructor for HumanPlayer the set the Player id and name but I don't seem to figure out how to set Player::id to the HumanPlayer::id.
This is what I have worked out but gives an error
"int Player::id' is private within this context"
HumanPlayer::HumanPlayer(int id, string name) : Player(id){
this -> id = id;
this -> name = name;
}
For your understanding.
class Player {
private:
int id;
protected:
std::string name;
public:
//Base class constructor, initialize Id.
Player(int i):id(i)
{}
~Player() {}
//Test
int GetId()
{
return id;
}
std::string GetName()
{
return name;
}
};
class HumanPlayer : public Player {
public:
HumanPlayer(int i, std::string s) :Player(i) //Pass on Id base class constructor
{
name = s; //Protected variable accessible.
}
};
void main()
{
HumanPlayer hPlayer(10, "Test");
std::cout << hPlayer.GetId() << std::endl;
std::cout << hPlayer.GetName() << std::endl;
}
Is it possible to access the child's function members from a pointer of an abstract class as the parent?
This is the abstract class
class Item {
public:
virtual double getTotalPrice() = 0;
};
This is the child class
class Product : public Item {
protected:
string name;
public:
Product() {}
string getName() {}
double getTotalPrice() {}
};
Is it possible in the main driver to access this getName() function from an instance of the Item class, as I want to display the total price and the name of the product also?
You need your base class to have a virtual destructor if you should be able to delete objects through a base class pointer.
Make getName virtual too.
class Item {
public:
virtual ~Item() = default;
virtual const string& getName() /* const */ = 0;
virtual double getTotalPrice() /* const */ = 0;
};
Note that the Product class that you aren't allowed to change is slightly flawed.
It doesn't return values where it should.
The getter member functions are not const.
Suggest some changes if you can't do it yourself:
class Product : public Item {
private: // prefer private member variables
string name;
public:
Product() = default;
const string& getName() const override { return name; }
double getTotalPrice() const override {
// why is this implemented here when there's no price to return?
return {};
}
};
You cannot have an instance of the abstract Item class (because it's abstract) but you can have an Item pointer (or reference) to a derived (and non-abstract) Product class.
But because Item declares no getName() , you'd probably need to do a dynamic_cast to check if the pointee is really a Product, for ex.
Item* item = new Product();
...
// at same later time or some ooter function:
// use dynamic_cast to check if the pointee is the type you expect it to be
Product* p = dynamic_cast<Product>(item);
if (p) p->getName();
Though, not directly targeting your question I think there is also a design issue here. Something like Product conists of many items so it's rather 1:N composition relationship. For getting total price a concept (for ex. Billable ) would be mnore appropriate.
So I would probably advise something like following for the class hierarhy:
class Billable
{
public:
virtual double getTotalPrice() const = 0;
virtual ~Billable() {}
};
class Item : public Billable
{
string name;
public:
string getName() const { return name; }
double getTotalPrice() const override { ... impl .. }
// ... rest
}
class Product : public Billable
{
string name;
vector<Items> items;
public:
string getName() const { return name; }
double getTotalPrice() const override
{
return accumulate(begin(items), end(items), 0, [](auto i) { return i->getTotalPrice(); });
}
// ... rest ...
}
You can static cast if you're sure that the pointer points to an actual object of type Product or dynamic cast if you're not sure and want to check it first. This doesn't work if the pointer doesn't point to an object of the derived class.
class Item {
public:
virtual double getTotalPrice() = 0;
};
class Product : public Item {
protected:
string name;
public:
Product() {}
string getName() {return {};}
double getTotalPrice() {return {};}
};
int main() {
Product p;
Item *i = &p;
static_cast<Product *>(i)->getName();
auto *ptr = dynamic_cast<Product *>(i);
if (ptr) ptr->getName();
}
dynamic_cast requires runtime type information (RTTP) and comes with some extra costs.
Usually it's better to redesign the architecture instead of downcast.
I have declared a class Products and another class CD the class CD is inheriting the class Products.
Now I have declared an constructor to update the value of the. and I am getting an error
#include <iostream>
#include <string>
class Products
{
private:
std::string name;
std::string type;
double price;
public:
virtual std::string getname();
virtual double getprice();
virtual void show();
std::string gettype()
{
return type;
}
};
class CD: public Products
{
private:
std::string artist;
std::string studio;
public:
CD(std::string sname,double sprice,std::string sartist,std::string sstudio)
{
this->type = "CD";
this->name = sname ;
this->price = sprice;
this->artist = sartist;
this->studio = sstudio;
}
void show()
{
std::cout<<"\nName of the CD:\t"<<this->name;
std::cout<<"\nArtist of the CD:\t"<<this->artist;
std::cout<<"\nStudio of the CD:\t"<<this->studio;
std::cout<<"\nPrice of the cd:\t"<<this->price;
}
};
int main()
{
CD obj("Oceans",49,"somesinger","somestudio");
}
ERROR :
In constructor 'CD::CD(std::string, double, std::string)';
'std::string Products::type' is private within this context
this->type="CD";
'std::string Products::name' is private within this context
this->name=sname;
'double Products::price' is private within this context
this->price= sprice;
Basically it is not giving error for the private data members of the CD class but just the data members that are being inherited from Products Class
#include <iostream>
#include <string>
class Products
{
private:
std::string m_name;
std::string m_type;
double m_price;
public:
// No need for your setters/getters to be virtual
// if the derived class won't override anything or not
const std::string& getType() const { return m_type; }
const std::string& getName() const { return m_name; }
double getPrice() const { return m_price; }
void setType(const std::string& new_type) { m_type = new_type; }
void setName(const std::string& new_name) { m_name = new_name; }
void setPrice(double new_price) { m_price = new_price; }
// Force derived class to override function
virtual void show() = 0;
};
class CD: public Products
{
private:
std::string artist;
std::string studio;
public:
CD(std::string sname,double sprice,std::string sartist,std::string sstudio)
{
this->setType("CD");
this->setName(sname) ;
this->setPrice(sprice);
this->artist = sartist;
this->studio = sstudio;
}
void show()
{
std::cout<<"\nName of the CD:\t"<<this->getName();
std::cout<<"\nArtist of the CD:\t"<<this->artist;
std::cout<<"\nStudio of the CD:\t"<<this->studio;
std::cout<<"\nPrice of the cd:\t"<<this->getPrice();
}
};
int main()
{
CD obj("Oceans",49,"somesinger","somestudio");
obj.show();
}
I want you to understand some changes here. First the removal of virtual keyword. In your case the setters/getters had no need to be virtual, as they were not being overriden or didn't have a need to be based on the current example. Second, the setters/getters are setup to access the private members accordingly. We now use these functions within class CD. Also we changed the function show() to be pure virtual notice the = 0 at the end. I added a comment saying this forces derived classes to override the function. Lastly, your main wasn't doing anything so I added a obj.show() to actually print something.
In this solution, I've added a constructor for Products, and CD's constructor calls it to initialize the members that are private to Products.
I removed the virtual on getName and getPrice since these features don't change other products.
show remains virtual, and I split it into a piece in Products and a piece in CD so they each display their respective fields. This separates the printing according to where the variables are, so for example, another class derived from Products wouldn't have to reimplement printing of name and price.
#include <iostream>
#include <string>
class Products
{
private:
std::string name;
std::string type;
double price;
public:
std::string getname(); // Does not need to be virtual, as it's not overriden
double getprice(); // Also does not need to be virtual
virtual void show() const {
std::cout<<"\nName of the " << type << ":\t"<<this->name;
std::cout<<"\nPrice of the " << type << ":\t"<<this->price;
};
Products (const std::string &stype, double sprice, const std::string &sname)
: name (sname), type (stype), price (sprice) {
}
std::string gettype() const
{
return type;
}
};
class CD: public Products
{
private:
std::string artist;
std::string studio;
public:
CD(const std::string &sname,double sprice, const std::string &sartist, const std::string &sstudio)
: Products ("CD", sprice, sname)
{
artist = sartist;
studio = sstudio;
}
void show() const override
{
Products::show(); // Call parent show() to show the basics
std::cout<<"\nArtist of the " << gettype() << ":\t"<<this->artist;
std::cout<<"\nStudio of the " << gettype() << ":\t"<<this->studio;
}
};
int main()
{
Products shoe ("Shoe", 3.49, "Nike runner");
shoe.show();
CD obj("Oceans",49,"somesinger","somestudio");
obj.show();
}
So i have this part of code
class Robot
{
public: string Name;
public: explicit Robot(const string& Name) { this->Name = Name; }
public: Robot() { Name = "Robotic"; }
public: virtual ~Robot() = default;
public: virtual vector<string> GetCapabilities() = 0;
public: friend ostream& operator << (ostream&, const Robot&);
};
class TalkingRobot : virtual public Robot
{
public: explicit TalkingRobot(const string& Name) { this->Name = Name; }
public: virtual ~TalkingRobot() = default;
public: vector<string> GetCapabilities() { return { "Talking" }; }
};
class WalkingRobot : virtual public Robot
{
public: explicit WalkingRobot(const string& Name) { this->Name = Name; }
public: virtual ~WalkingRobot() = default;
public: vector<string> GetCapabilities() { return { "Walking" }; }
};
class VaxBot : public TalkingRobot, public WalkingRobot
{
public: explicit VaxBot(const string& Name):TalkingRobot(Name), WalkingRobot(Name) { this->Name = Name; }
public: virtual ~VaxBot() = default;
public: vector<string> GetCapabilities() { return { "Talking","Walking" }; }
};
They have a virtual function GetCapabilites().
Is there a way to rewrite GetCapabilites() in my VaxBot class to return all the inherited classes return values so that i dont have to explicitly write them like i did in here?
There isn't a simple one-line way in standard C++ to implement this sort of thing. For example, there is no way for a derived class to iterate over all its base classes, and call some member function in every base to collect the results, without explicitly naming all the bases/members separately.
It is possible to call the inherited functions, and collect their results into a single vector. For example;
std::vector<std::string> VaxBot::GetCapabilities()
{
std::vector<std::string> values(TalkingRobot::GetCapabilities());
std::vector<std::string> more_values(WalkingRobot::GetCapabilities());
values.insert(values.end(), more_values.begin(), more_values.end());
return values;
}
The above can be extended if you have more than two such bases. That means explicitly replicating code but, as I said in my opening paragraph, there is no way to implement this sort of machinery implicitly.
There are other problems with your code, but you haven't asked about those, so I won't address them. And, for readability, don't use the text public: on every line. Posting code that is unnecessarily unreadable is an effective way to reduce your chances of getting useful help, since it sets other people's teeth on edge.
class Robot
{
public: string Name;
public: vector<string> Capabilities;
public: explicit Robot(const string& Name) { this->Name = Name; }
public: Robot() { Name = "Robotic"; }
public: virtual ~Robot() = default;
public: vector<string> GetCapabilities() { return this->Capabilities; }
public: friend ostream& operator << (ostream&, const Robot&);
};
class TalkingRobot : virtual public Robot
{
public: explicit TalkingRobot(const string& Name) {
this->Name = Name;
this->Capabilities.push_back("Talking");
}
public: virtual ~TalkingRobot() = default;
};
class WalkingRobot : virtual public Robot
{
public: explicit WalkingRobot(const string& Name) {
this->Name = Name;
this->Capabilities.push_back("Walking");
}
public: virtual ~WalkingRobot() = default;
};
class VaxBot : public TalkingRobot, public WalkingRobot
{
public: explicit VaxBot(const string& Name):TalkingRobot(Name), WalkingRobot(Name) { this->Name = Name; }
public: virtual ~VaxBot() = default;
};
You could utilize multiple inheritance constructors to store Capabilities.
I have a base class called Animal:
class Animal {
protected:
std::string name;
int age;
int weight;
public:
Animal(const std::string& _name, int _age, int _weight):name(_name),age(_age),weight(_weight) {};
virtual void animal_cange(Animal*) = 0;
};
and from the Animal class derives two sublasses
class Dog : public Animal {
public:
Dog(const std::string& _name, int _age, int _weight) :Animal(_name, _age, _weight) {};
void animal_cange(Animal* poot) override {
this = new Cat(poot->name,poot->age,poot->weight);
}
};
and this
class Cat : public Animal {
public:
Cat(const std::string& _name, int _age, int _weight) :Animal(_name, _age, _weight) {};
void animal_cange(Animal* poot) override {
this = new Dog(name, age, weight);
}
};
I made a virtual funcion in the base class caled virtual void animal_cange(Animal*) = 0; which should change a Dog object to a Cat object if it is called with the object's already existing name, age and weight value and visa versa but it always gives me error like:
assignment to 'this' (anachronism)
a value of type "Cat *" cannot be assigned to an entity of type "Dog *"
protected member "Animal::name" (declared at line 12) is not accessible through a pointer or object
I also tried without animal_change being a virtual function like this:
class Animal {
protected:
std::string name;
int age;
int weight;
public:
Animal(const std::string& _name, int _age, int _weight):name(_name),age(_age),weight(_weight) {};
};
class Dog : public Animal {
public:
Dog(const std::string& _name, int _age, int _weight) :Animal(_name, _age, _weight) {};
void animal_cange() {
this = new Cat(this->name,this->age,this->weight);
}
};
class Cat : public Animal {
public:
Cat(const std::string& _name, int _age, int _weight) :Animal(_name, _age, _weight) {};
void animal_cange() {
*this = new Dog(name, age, weight);
}
};
And the erorrs i get:
this = new Cat(this->name,this->age,this->weight); : "assignment to 'this' (anachronism)" and the entity error
"no operator matches these operands operand types are: Cat = Dog *"
In general, you cannot assign an object to one of a different class - that's what static type system is about. To "change" the dynamic type of a polymorphic object the client code can create another one like this:
Animal* animal = new Dog{}; // actually you should use smart pointers
if (want_to_change) {
delete animal; // prevents a memory leak; smart pointers perform it automatically
animal = new Cat{};
}
If you would like actual animal type choice to happen during initialization, consider using a factory:
class Factory {
public:
// may be static if uses no state, than you can just write a free function
Animal* produce(/* some parameters */) const;
};
Animal* Factory::produce(/* some parameters */) const {
if (should_be_cat(/* depending on the parameters */)) {
return new Cat{};
} else {
return new Dog{};
}
}