0

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.

SQTX
  • 13
  • 3
  • 4
    When you assign a derived class instance to this array `Animal animals[2];` you're slicing away everything but the base class. – Retired Ninja Dec 29 '21 at 22:45
  • 3
    Does this answer your question? [What is object slicing?](https://stackoverflow.com/questions/274626/what-is-object-slicing) – Retired Ninja Dec 29 '21 at 22:47
  • 2
    You probably want something like: `Animal* animalPtrs[2]={&dog, &cat};` – Jarod42 Dec 29 '21 at 22:48
  • I see. Actually, I got a message about slicing from Clion. So to the array, instead of objects, I should assign pointers to objects. It makes sense and it works. Thank you so much for help. – SQTX Dec 29 '21 at 22:55
  • When you create an object In Java and assign it into an array Java stores a pointer to the original object. In C++ an array of `Animal` objects stores `Animal` objects, not pointers. That’s why some of the comments suggest storing pointers; that’s more like what Java does. – Pete Becker Dec 29 '21 at 22:56
  • @SQTX *When I wrote the same application in Java* -- C++ is not Java. Do not use Java as a model in writing C++ code. Pretend Java never existed and learn C++ from that perspective. If you write C++ using Java as a model, you end up with either inefficient code, buggy code, or code that looks weird to a C++ programmer. The `instanceof` you do in Java, to me, defeats the entire purpose of polymorphism, thus do not introduce that into a C++ program on purpose by using `dynamic_cast`. Using `dynamic_cast` is a code smell -- you better have a good reason to use it in a C++ program. – PaulMcKenzie Dec 30 '21 at 00:39

1 Answers1

0

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)

pm100
  • 48,078
  • 23
  • 82
  • 145