0

I am learning polymorphism and I am familiar with php.

I came across this excellent example from https://stackoverflow.com/a/749738/80353. reproduced below.

How do I write the same code, but in C++?

I have a problem writing it myself because I believe (I may be wrong) that the data structures in C++ are strict.

You must have all the elements inside a linkedlist or array in C++ of the same type.

So I believe that you need to store the cat and dog as their base class into the data structure.

So how do I write this php code snippet into a C++ code snippet that uses a strict data structure that it can only store elements of 1 data type?

class Animal {
    var $name;
    function __construct($name) {
        $this->name = $name;
    }
}

class Dog extends Animal {
    function speak() {
        return "Woof, woof!";
    }
}

class Cat extends Animal {
    function speak() {
        return "Meow...";
    }
}

$animals = array(new Dog('Skip'), new Cat('Snowball'));

foreach($animals as $animal) {
    print $animal->name . " says: " . $animal->speak() . '<br>';
}
Community
  • 1
  • 1
Kim Stacks
  • 10,202
  • 35
  • 151
  • 282
  • Not a C++ programmer but I hear you can have a list of `Animal`s and still populate it with `Animal` subclasses (e.g. `Cat`s and `Dog`s). – Waleed Khan Nov 04 '12 at 04:14
  • Can you give me an example? I am not familiar with C++ syntax and googling for "dynamic list C++" did not help me much. – Kim Stacks Nov 04 '12 at 05:33

3 Answers3

0

Well, you can use a pointer with abstract classes using pure virtual methods like so:

class Polygon {
    public:
        virtual void setValue(int k) = 0;    // Declaring our pure virtual method.
};

class Rect : public Polygon {
    public:
        virtual void setValue(int k); = 0;   // Declaring the pure virtual method again.
};

Rect::setValue(int k) {    // You must create a setValue() method for every class, since we made a pure virtual method. This is the Polymorphic part.
    // Code in here that setValue() method executes.
    int foo = a;
    std::cout << foo << std::endl;
}

Now you can access the methods declaring object pointers.

int main() {
    Polygon* pSomePolygon = nullptr;   // Assuming using C++11.
    Rect* pRect = new Rect;    // Declare our object.

    pSomePolygon = pRect;    // Point our pointer to object 'pRect'.

    pSomePolygon->setValue(18);    // Pointer accesses pRect and uses the pure virtual method.
    delete pRect;    // Clean up!

    return 0;
}
Tux
  • 1,896
  • 3
  • 19
  • 27
  • thank you for your attempt. But I preferred a direct translation of the php code above so it is easier for me to appreciate polymorphism. – Kim Stacks Nov 04 '12 at 05:33
  • @kimsia No one wants to write YOUR code for you. If you want to learn how, you gotta do it yourself. You won't learn anything from me writing your code, but you will learn how to do it properly from writing it yourself. I showed you how to program it in C++; thus, I answered your question. If you want someone to write your code for you, offer them a job and pay them money. – Tux Nov 04 '12 at 05:46
  • There must be some kind of misunderstanding. I am not here to sponge off people and pass off other people code as mine. Thank you for your reply. – Kim Stacks Nov 04 '12 at 10:54
  • @kimsia I know that, but you are clearly asking someone else to do YOUR code for you. – Tux Nov 04 '12 at 16:30
0

Since you only asked about storing them, I'll omit the implementation of Animal, Dog and Cat.

vector< shared_ptr<Animal> > animals;
animals.push_back( new Dog("Skip") );
animals.push_back( new Cat("Snowball") );

for( size_t i = 0; i< animals.size(); ++i )
    cout << animals[i]->name << " says: " << animals[i]->speak() << endl;

Essentially you need to store pointers to the objects. Put simply, shared_ptr<T> is a class that stores a pointer and deletes it when it is no longer referenced.

Alex
  • 7,728
  • 3
  • 35
  • 62
0

As someone not familiar with C++, create a index.cpp file and fill it up with the following

#include <iostream>
#include <vector>
#include <memory>

using namespace std;

class Animal {
  public:
    std::string name;
    Animal (const std::string& givenName) : name(givenName) {}
    virtual string speak () = 0;
    virtual ~Animal() {}

  };

class Dog: public Animal {
  public:
    Dog (const std::string& givenName) : Animal (givenName) {

    }
    string speak ()
      { return "Woof, woof!"; }
  };

class Cat: public Animal {
  public:
    Cat (const std::string& givenName) : Animal (givenName) {
    }
    string speak ()
      { return "Meow..."; }
  };

int main() {
    std::vector<std::unique_ptr<Animal>> animals;
    animals.push_back( std::unique_ptr<Animal>(new Dog("Skip"))  );
    animals.push_back( std::unique_ptr<Animal>(new Cat("Snowball"))  );

    for( int i = 0; i< animals.size(); ++i ) {
        cout << animals[i]->name << " says: " << animals[i]->speak() << endl;
    }

}

afterwards, compile the index.cpp file with the following command

c++ index.cpp -std=c++11 -stdlib=libc++

you need that because of the use of smart pointers unique_ptr in the code.

finally you can execute the compiled executable output file which should be a.out

./a.out
Kim Stacks
  • 10,202
  • 35
  • 151
  • 282