Code:
#include <iostream>
#include <string>
using namespace std;
class Mammal {
public:
int age;
Mammal() {age = 55;}
void say() {
cout << "I'm a Mammal and my age " << age;
}
};
class Reptile {
public:
int age;
Reptile() {age = 77;}
void say() {
cout << "I'm a Reptile and my age " << age;
}
};
class Platypus: public Mammal, public Reptile {
public:
Platypus() :
Mammal(), Reptile() {
cout << "Constructed!" << endl;
}
};
int main() {
Platypus p;
p.Mammal::say();
p.Reptile::say();
}
And result is:
I'm a Mammal and my age 4215460
I'm a Reptile and my age 4215472
Why:
1. Platypus constructor wasn't called and "Constructor" wasn't output?
2. ages in parents are still random (parent constructors wasn't called too?)
Related
I created two objects from derived classes (Dog and Cat), which I assigned to one common array, which is the Animal type. Now I want to check a single element of the array to see if it is a dog. If there is, I want it to execute a method from Dog class and bark.
#include <iostream>
using namespace std;
class Animal{
public:
Animal() {}
virtual ~Animal() {}
};
class Dog : public Animal{
public:
Dog() {}
virtual ~Dog() {}
void soundOf(){
cout << "Woof woof" << endl;
}
};
class Cat : public Animal{
public:
Cat() {}
virtual ~Cat() {}
void soundOf(){
cout << "Meoow" << endl;
}
};
int main() {
Animal animals[2];
Dog dog;
Cat cat;
animals[0] = dog;
animals[1] = cat;
Animal *ptr = animals+0;
Dog* dg = dynamic_cast<Dog*>(ptr);
if(dynamic_cast<Dog*>(ptr) != nullptr){
cout << "This is a dog" << endl;
dg->soundOf();
}else if(dynamic_cast<Cat*>(ptr) != nullptr){
cout << "This is a cat" << endl;
dg->soundOf();
}
return 0;
In "if", I also used the following method
if(Dog* dg = dynamic_cast<Dog*>(ptr))
But the effect was the same. It returned NULL every time.
When I wrote the same application in Java, it was enough to use "instanceof", but here I can't do it.
Others have commented as to why you are having this issue but have not really suggested a fix. You should get into the habit of using dynamically allocated objects and ensuring they behave nicely by using std::shared_ptr and std::vector.
#include <iostream>
#include <vector>
#include <memory>
using namespace std;
class Animal
{
public:
Animal() {}
virtual void soundOf() {}
virtual ~Animal() {}
};
class Dog : public Animal
{
public:
Dog() {}
virtual ~Dog() {}
void soundOf()
{
cout << "Woof woof" << endl;
}
};
class Cat : public Animal
{
public:
Cat() {}
virtual ~Cat() {}
void soundOf()
{
cout << "Meoow" << endl;
}
};
typedef std::shared_ptr<Animal> AnimalPtr;
int main()
{
std::vector<AnimalPtr> animals;
AnimalPtr dog = std::make_shared<Dog>();
AnimalPtr cat = std::make_shared<Cat>();
animals.push_back(dog);
animals.push_back(cat);
AnimalPtr ptr = animals[0];
if (dynamic_cast<Dog *>(ptr.get()) != nullptr)
{
cout << "This is a dog" << endl;
ptr->soundOf();
}
else if (dynamic_cast<Cat *>(ptr.get()) != nullptr)
{
cout << "This is a cat" << endl;
ptr->soundOf();
}
return 0;
}
this might seem long winded but will scale much better (and provides the functionality you want)
I have this UML Diagram and I have written the code below but I am struggling with an error message
However, while compiling and linking, I got an error
/tmp/cc9oQaPX.o: In function `main':
main.cpp:(.text+0x8c): undefined reference to `Fish::Fish(std::string)'
main.cpp:(.text+0xe5): undefined reference to `Cat::Cat(std::string)'
main.cpp:(.text+0x116): undefined reference to `Fish::Fish()'
main.cpp:(.text+0x158): undefined reference to `Cat::Cat()'
collect2: error: ld returned 1 exit status
#include <iostream>
using namespace std;
class Animal // define base class
{
protected:
int legs; // base class properties
public:
Animal(int legNumbers) // set values of leg
{
legNumbers = legs; // set values of leg
}
virtual void eat() = 0; // method of base class
virtual void walk() {}; // method of base class
};
class Pet // define the pet class
{
protected:
string name; // set properties of pet class
public:
virtual string getName(); // define method
virtual string setName(string name); // set name values
virtual void play() // define play method
{
cout << " garfield is playing now." << endl; // out values
}
};
class Spider :public Animal //child class inherit base class
{
public:
Spider() :Animal(8) // spider class inherit animal class
{
cout << "animals with " << legs << " legs is walking. " << endl;
}
virtual void eat() // define virtual method
{
cout << "spider is eating now. " << endl;
}
};
class Cat :public Pet, public Animal // cat inherit two classes
{
public:
Cat(string name); // set name method
Cat();
virtual void play() // define method
{
cout << name << " is playing now. " << endl;
}
virtual void eat(); // define method here
};
class Fish : public Pet, public Animal // fish inherit two method
{
public: // define public members
Fish(string name);
Fish();
virtual void play()
{
cout << name << " is playing now. " << endl;
}
virtual void eat(); // method here
void walk()
{
cout << " Fish cannot walk " << endl; // output the values
}
};
string Pet::getName() // get name value from parent class
{
return string();
}
string Pet::setName(string name)
{
return string();
}
int main(int argc, char* argv[]) // define main method
{
Fish* f = new Fish("Jaws");
Cat* c = new Cat("Tenkir");
Animal *a = new Fish();
Animal* e = new Spider();
Pet* p = new Cat();
f->play();
c->play();
e->eat();
e->walk();
a->walk();
p->play();
return 0;
}
This is right code.
Firstly, you didn't defined the constructors for Cat an Fish
But that wasn't the only problem.
Your functions walk, eat, play need to be override. And eat() has to have a block, becuase in the base class (Animal) is deleted, like eat() = 0;
#include <iostream>
using namespace std;
class Animal // define base class
{
protected:
int legs; // base class properties
public:
Animal(int legNumbers) // set values of leg
{
legs = legNumbers; // set values of leg
}
virtual ~Animal() {}
virtual void eat() = 0; // method of base class
virtual void walk() {}; // method of base class
};
class Pet // define the pet class
{
protected:
string name; // set properties of pet class
public:
virtual string getName(); // define method
virtual void setName(string name); // set name values
virtual void play() // define play method
{
cout << " garfield is playing now." << endl; // out values
}
};
string Pet::getName() // get name value from parent class
{
return this->name;
}
void Pet::setName(string name)
{
this->name = name;
}
class Spider :public Animal //child class inherit base class
{
public:
Spider() :Animal(8) // spider class inherit animal class
{
cout << "animals with " << legs << " legs is walking. " << endl;
}
virtual void eat() // define virtual method
{
cout << "spider is eating now. " << endl;
}
};
class Cat :public Pet, public Animal // cat inherit two classes
{
public:
Cat(string name)
:Animal(4)
{
this->setName(name);
} // set name method
Cat():Animal(4){}
~Cat() override {}
virtual void play() override // define method
{
cout << name << " is playing now. " << endl;
}
virtual void eat() override {} // define method here
};
class Fish : public Pet, public Animal // fish inherit two method
{
public: // define public members
Fish(string name)
:Animal(0)
{
this->setName(name);
}
Fish():Animal(0){}
~Fish() override {}
virtual void play() override
{
cout << name << " is playing now. " << endl;
}
virtual void eat() override {} // method here
void walk() override
{
cout << " Fish cannot walk " << endl; // output the values
}
};
int main(int argc, char* argv[]) // define main method
{
Fish* f = new Fish("Jaws");
Cat* c = new Cat("Tenkir");
Animal *a = new Fish();
Animal* e = new Spider();
Pet* p = new Cat();
f->play();
c->play();
e->eat();
e->walk();
a->walk();
p->play();
return 0;
}
I have a class derived from base class, and set constructors for each classes, but I keep getting error that I do not have any constructor for base class.
class Dog
{
protected:
string name;
int age;
public:
Dog(string dogsName, int dogsAge)
{
name = dogsName;
age = dogsAge;
}
virtual void Bark()
{
cout << "Woof Woof I am a dog" << endl;
}
class Huey: public Dog
{
public:
Huey()
{
name = "goodboy";
age = 13;
}
void Bark()
{
cout << "woof" << endl;
}
}
Here I get an error on Huey() and it says " no default constructor exists for 'Dog'". But I think I have created a constructor for class Dog. Can you please explain why this code is wrong?
When you specify any constructor of your own, the default constructor is not created anymore. However, you can just add it back.
class Dog
{
protected:
string name;
int age;
public:
Dog() = default;
Dog(string dogsName, int dogsAge)
{
name = dogsName;
age = dogsAge;
}
virtual void Bark()
{
cout << "Woof Woof I am a dog" << endl;
}
};
class Huey: public Dog
{
public:
Huey()
{
name = "goodboy";
age = 13;
}
void Bark()
{
cout << "woof" << endl;
}
};
EDIT: It seems like you want to call your custom Dog constructor from Huey. It is done like so
class Dog
{
protected:
string name;
int age;
public:
Dog(string dogsName, int dogsAge)
{
name = dogsName;
age = dogsAge;
}
virtual void Bark()
{
cout << "Woof Woof I am a dog" << endl;
}
};
class Huey: public Dog
{
public:
Huey() : Dog("goodboy", 13) {}
void Bark()
{
cout << "woof" << endl;
}
};
You need to create a constructor with no parameters and no implementation. As below:
public:
Dog() = default;
Two ways:
1) have a default constructor with no params.
2) call the existing constructor you have in Dog from Huey ( this is the right thing in your case since Huey is a Dog after all). Huey is currently calling the default constructor of Dog since this isn’t defined and explicitly called.
I'm trying to become accustomed to classes. Here I've made a base class called Animal and a derived class called Dog.
I was originally able to to get the base class to work alone, but when I tried adding a derived class, things got messy and I got errors. Here is the code, and if you could let me know what I'm doing wrong, that'd be great!
#include <iostream>
#include <string>
using namespace std;
class Animal{
protected:
int height, weight;
string name;
public:
int getHeight() { return height; };
int getWeight() { return weight; };
string getName() { return name; };
Animal();
Animal(int height, int weight, string name);
};
Animal::Animal(int height, int weight, string name){
this->height = height;
this->weight = weight;
this->name = name;
}
class Dog : public Animal{
private:
string sound;
public:
string getSound() { return sound; };
Dog(int height, string sound);
};
Dog::Dog(int height, string sound){
this->height = height;
this->sound = sound;
}
int main()
{
Animal jeff(12, 50, "Jeff");
cout << "Height:\t" << jeff.getHeight << endl;
cout << "Weight:\t" << jeff.getWeight << endl;
cout << "Name:\t" << jeff.getName << endl << endl;
Dog chip(10, "Woof");
cout << "Height:\t" << chip.getHeight() << endl;
cout << "Sound:\t" << chip.getSound() << endl;
}
The default constructor for the Animal class is not defined. You need:
Animal::Animal() : height(0), weight(0) // Or any other desired default values
{
}
You should also have a virtual destructor on the base class.
class Animal
{
public:
~Animal() {} // Required for `Animal* a = new Dog(...); delete a;`
// deletion via base pointer to work correctly
};
Edit:
Upon removal of Animal() I get an error that says 'Animal': no appropriate default constructor available
You need to implement the default constructor (see above). Without it the int members will not be initialized and have undefined values.
I have the code:
#include <iostream>
#include <cstdlib>
using namespace std;
class Animal{
private:
int age;
public:
Animal() : age(1) {}
void toString(){
cout << "Age: " << age << endl;
}
};
class Cat : public Animal
{
public:
Cat() : age(5) {}
/*
void toString(){
cout << "Age: " << age << endl;
}*/
private:
int age;
};
int main(){
Cat tom;
tom.toString();
system("pause");
return 0;
}
But when I run the program, the age of the tom variable is 1, not 5. Does the toString can not read the age variable? If we open the /* */ the toString method in the Cat class, the age will be 5 !
(My english is not good very much. Thanks)
The problem is that Cat is writing to the age variable in Cat, while toString() reads the age variable in Animal, which, with Animal's constructor, is initialized to 1.
To solve this, you can provide another constructor for Animal which accepts an age parameter which is used to initialize Animal's age member variable.
class Animal{
private:
int age;
public:
Animal() : age(1) {}
Animal(int param_age) : age(param_age) {} // Initialize member variable age with parameter
void toString(){
cout << "Age: " << age << endl;
}
};
class Cat : public Animal
{
public:
Cat() : Animal(5) {} // Call Animal's constructor that set's the age
};
UPDATE: Another solution is to add a setter method in Animal class that sets its age. You can then call it in Cat's constructor to set the proper age.
class Animal{
private:
int age;
public:
Animal() : age(1) {}
void setAge(int age) { this->age = age; }
void toString(){
cout << "Age: " << age << endl;
}
};
class Cat : public Animal
{
public:
Cat() {
setAge(5);
}
};
Yet another alternative is to make Animal's age member protected
class Animal{
protected: // THIS
int age;
public:
Animal() : age(1) {}
void toString(){
cout << "Age: " << age << endl;
}
};
And remove Cat's age variable in the class definition. Despite its simplicity, this approach gives you more risk in encountering the "brittle base class" problem. Thus, I recommend the former solution as it is less prone to the said problem, and IMHO better sticks to the "write against interfaces, not implementations" principle.
The problem is that you are setting Cat::age in the Cat constructor, not the Animal::age used by Animal::toString.
Change the visibility of Animal::age to protected.
class Animal {
protected:
int age;
public:
Animal() : age(1) {}
void toString(){
cout << "Age: " << age << endl;
}
};
Don't redeclare a second age (which becomes Cat::age). Instead, change the value of age (Animal::age).
class Cat : public Animal {
public:
Cat() {
age = 5;
}
};
Try:
#include <iostream>
#include <cstdlib>
using namespace std;
class Animal{
private:
int age;
public:
Animal(int a = 1) // Pass in the age as a parameter.
: age(a) // Default to 1.
{}
// Prefer generic print function rather than toString()
friend std::ostream& operator<<(std::ostream& s, Animal const& a) {
return s << "Age: " << a.age << '\n'; // Prefer '\n' rather than endl
// Unless you really want to flush
// the stream (this is not usually
// the case).
}
};
class Cat : public Animal
{
public:
Cat()
: Animal(5) // Now you can call the base class constructor
{} // And get it to set 5
private:
// int age; // don't have a private copy here.
// use the one that is available in the base class.
// Prefer generic print function rather than toString()
friend std::ostream& operator<<(std::ostream& s, Cat const& a)
{
// Print Cat
// Then use the Animal priting function to print more information about the object.
return s << "A Cat: " << static_cast<Animal const&>(*a);
}
};
int main(){
Cat tom;
// tom.toString(); // Don't use a toString() method.
// overload operator<< to print to a stream.
// If you want to convert to a string the just print
// to a string stream.
std::cout << tom;
system("pause");
return 0;
}