How can I override a virtual function in a derived class? - c++

I am trying to build a zoo for practicing c++ and oop. I have made 2 classes, Animal class (the base class) and Bear class (the derived class). I want to have 2 virtual functions in Animal that I will override in Bear but CLION tells me that 'Function Walk did not decleared in class Bear'.
What do I need to change?
This is the base class (Animal) header:
class Animal {
public:
Animal();
Animal(string Name, int CageNum, string FoodType, string Gender, bool NeedTreatment);
virtual void Talk() = 0;
virtual void Walk();
int CageNum;
string FoodType;
string Gender;
bool NeedTreatment;
string Name;
};
CPP:
Animal::Animal() {};
Animal::Animal(string Name, int CageNum, string FoodType, string Gender, bool NeedTreatment) :
Name(Name), CageNum(CageNum), FoodType(FoodType), Gender(Gender), NeedTreatment(NeedTreatment){};
This is the derived class (Bear) header:
#include "Animal.h"
class Bear : public Animal{
protected:
string FurColor;
public:
Bear(string Name, int CageNum, string FoodType, string Gender, bool NeedTreatment,string FurColor);
};
and this is the CPP:
#include "Bear.h"
Bear::Bear(string Name, int CageNum, string FoodType, string Gender, bool NeedTreatment,string FurColor) :
Animal(Name, CageNum, FoodType, Gender, NeedTreatment),FurColor(FurColor) {};
void Bear::Walk() {
cout << "Bear Moves";
}
void Animal::Talk() {
"Bear Noise";
}

If you define a function like
void Bear::Walk() {
cout << "Bear Moves";
}
its declaration must appear in the class definition:
class Bear : public Animal{
protected:
string FurColor;
public:
Bear(string Name, int CageNum, string FoodType, string Gender, bool NeedTreatment,string FurColor);
void Walk() override; // <<<<<<<<<<<<<<<<<<
};
Alternatively you can omit the definition, and the base class member definition Animal::Walk() will be used.
Also
void Animal::Talk() {
"Bear Noise";
}
is wrong (or at last doesn't do what is intended).
A pure virtual function like Talk() from the base class, must have a declaration and definition in the Bear class, unless the class is intentionally left abstract.
class Bear : public Animal{
protected:
string FurColor;
public:
Bear(string Name, int CageNum, string FoodType, string Gender, bool NeedTreatment,string FurColor);
void Talk() override; // <<<<<<<<<<<<<<<<<<
void Walk() override;
};
and the definition
void Bear::Talk() {
"Bear Noise";
}

Related

can someone please explain what is wrong in this c++ code and provide a solution

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();
}

How to change a class to another class which derive from the same base class?

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{};
}
}

C++ No Appropriate Default Constructor I am lost

I am stuck on a problem involving Polymorphism. My code keeps telling me that there is no default constructor for my class in this case I named creature, even though I did instantiate a constructor that takes a string in the creature class. I have a feeling I am missing something very small here and was hoping someone could help me with this. The code is as follows below.
class Creature
{
public:
Creature(string);
virtual void DoAction() = 0;
virtual void DrawOnScreen() = 0;
protected:
string CreatureName;
};
Creature::Creature(string pname)
{
this->CreatureName = pname;
};
class Monster : public Creature
{
Monster(string CreatureName);
void DoAction();
protected:
string CreatureName;
};
Monster::Monster(string pname)
{
this->CreatureName = pname;
};
class Player : public Creature
{
Player(string CreatureName);
void DoAction();
protected:
string CreatureName;
};
Player::Player(string pname)
{
this->CreatureName = pname;
}
class WildPig : public Creature
{
WildPig(string CreatureName);
void DoAction();
protected:
string CreatureName;
};
WildPig::WildPig(string pname)
{
this->CreatureName = pname;
}
class Dragon : public Creature
{
Dragon(string CreatureName);
void DoAction();
protected:
string CreatureName;
};
Dragon::Dragon(string pname)
{
this->CreatureName = pname;
}
I only included the classes within this snippet to keep it short and focused on where I believe the problem lies. Any help would be greatly appreciated.
Monster::Monster(string pname)
{
this->CreatureName = pname;
}
is equivalent to
Monster::Monster(string pname) : Creature()
{
this->CreatureName = pname;
}
And Creature doesn't have default constructor. You need:
Monster::Monster(string pname) : Creature(pname) {}

C++ unable to use super class' methods?

I feel stupid right now, haven't been doing C++ in ages, can't understand what's wrong... However I got this following class:
#include <string>
class NamedObject
{
public:
NamedObject();
virtual ~NamedObject();
virtual std::string getName() const { return m_name };
virtual void setName(const std::string name) { m_name = name };
private:
std::string m_name;
};
And now I'm inheriting a simple class out of it:
#include "NamedObject.h"
enum eTeam { eAttacker, eDefender, eSpectator, eNone };
class Player : public NamedObject
{
public:
Player();
virtual ~Player();
virtual void printName();
virtual eTeam getTeam() const { return m_team };
virtual void setTeam(const eTeam team) { m_team = team };
private:
std::string m_name;
eTeam m_team;
};
However, I am unable to use player->setName("blabla") from my main.cpp? Here's the main file:
#include "Player.h"
int main()
{
Player* p1 = new Player();
p1->setName("Name Changed!")
p1->printName(); // prints "Unnamed" since I declared that in default ctor
return 0;
}
I'm not getting any errors, everything runs up well, the name just doesn't simply change. Also, I got all of the constructors and destructors, as well as my printName-method working perfectly, and the problem is not within them.
What you see is that setName modifies the m_name in the parent class and printName prints out the m_name of the derived class because you're redeclaring std::string m_name; in the derived class.
Remove the declaration from the derived class and mark m_name as protected member in the parent class:
#include <string>
class NamedObject
{
public:
NamedObject();
virtual ~NamedObject();
virtual std::string getName() const { return m_name };
virtual void setName(const std::string name) { m_name = name };
protected:
std::string m_name;
};
You could also keep m_name private and use the method getName() instead, as suggested by moswald.
You created another different variable m_name in your derived class that shadowed the one in the parent class.
I can see that must not be your real code.
Your derived/super class is redeclaring m_name. Probably not what you mean to do;)

List iterator outside range

I have a problem with the STL list class. I have a base class called Contact, and three derived classes, Friend, Colleague and Acquaintance. Each instance of the derived classes has certain fields which I modify in the fill*Class*Details() function. The problem is that when it reaches the push_back line, my program gives me an error saying list insert iterator outside range. What can that be from?
void Agenda::pushContact(string line, string temp)//function that adds a contact of type temp, containing the fields from line to the list
{
Contact *c;
if(temp=="friend") //the contact to add is of type friend
{
c = new Friend();
fillFriendDetails(c,line);//the details of Friend c will be filled
}
else if(temp=="colleague")
{
c = new Colleague();
fillColleagueDetails(c,line);//the details of Colleague c will be filled
}
else if(temp=="acquaintance")
{
c = new Acquaintance();
fillAcquaintanceDetails(c,line);//the details of Acquaintance c will be filled
}
contactList.push_back(c);
}
Also, the contactList is defined as list <Contact*> contactList;.
Edit: This is how the Contact class (+derived classes) are defined:
class Contact
{
public:
string getFullName() { string fullName;fullName.append(firstName); fullName.append(" ");fullName.append(lastName); return fullName;}
public:
void setFullName(string newFirstName, string newLastName) { firstName = newFirstName; lastName = newLastName;}
public:
string getFirstName() { return firstName;}
public:
void setFirstName(string newFirstName) {firstName = newFirstName;}
public:
string getLastName(){return lastName;}
public:
void setLastName(string newLastName){lastName = newLastName;}
public:
string getPhoneNo(){return phoneNo;}
public:
void setPhoneNo(string newPhoneNo) {phoneNo = newPhoneNo;}
public:
void setType(string newType){type=newType;}
public:
string getType(){return type;}
private:
string firstName;
string lastName;
string phoneNo;
string type;
//SubClass setters and getters
public:
virtual void setDateOfBirth(string birth) {}
virtual string getDateOfBirth() {return 0;}
virtual void setCity (string newCity) {}
virtual string getCity() {return 0;}
virtual void setFaculty (string newFaculty) {}
virtual string getFaculty() {return 0;}
virtual void setGroup (string newGroup) {}
virtual string getGroup() {return 0;}
virtual void setJob (string newJob) {}
virtual string getJob () {return 0;}
};
class Friend : public Contact
{
public:
void setDateOfBirth(string birth) {dateOfBirth=birth;}
public:
string getDateOfBirth() {return dateOfBirth;}
public:
void setCity (string newCity){city=newCity;}
public:
string getCity(){return city;}
private:
string dateOfBirth;
string city; //current city of residence
};
class Colleague : public Contact
{
public:
void setFaculty (string newFaculty){faculty = newFaculty;}
public:
string getFaculty(){return faculty;}
public:
void setGroup (string newGroup){group = newGroup;}
public:
string getGroup(){return group;}
private:
string faculty;
string group;
};
class Acquaintance : public Contact
{
public:
void setJob (string newJob){job=newJob;}
public:
string getJob (){return job;}
private:
string job;
};
It looks like the list is being mismanaged at a different point in the code, because the error implies end is incorrect. Most likely either the list is deleted/out of scope or some incorrect erases were performed on the list elements (say using invalid iterators).