0

I would like to ask about something like "instanceof" in Java. I created a simple example of inheritence. My idea was made an abstarct class Monster and children Skeleton and Zombie, but with abstract it doesn't work, so We have std::vectorBase class. I pushed children objects into vector. I want to call method of children classes, but method which is called is base class empty method. Is existing any way to do it ? Maybe in c++ programming we should avoid this code thinking and do it using vector skeleton and vector zombie separately? Sorry for my english. I hope you understand my problem.

 class Monster
        {
        public:
            virtual void describe() {};

        };

    class Skeleton : public Monster
        {
        public:
            Skeleton() {

            }
            ~Skeleton(){}
            void describe() override {
                std::cout << "I am skeleton" << std::endl;
            }
        };

    class Zombie : public Monster
        {
        public:
            Zombie(){}
            ~Zombie(){}
            void describe() override {
                std::cout << "I am Zombie" << std::endl;
            }
        };


        int main(void) {

            std::vector<Monster> potwory;
            potwory.push_back(Skeleton());
            potwory.push_back(Zombie());

            Skeleton sz;
            Zombie z;

            potwory.push_back(sz);
            potwory.push_back(z);

            for (auto i = 0; i < potwory.size(); i++) {
                std::cout << typeid(potwory[i]).name() << std::endl; // each of them is Monster object
                potwory[i].describe();  //here is calling method from base class , I want derived method.  
            }

            std::cin.get();
            return 0;

        }`
  • I'm a little confused by your question. Could you try to clarify what you need? – Remixt Feb 06 '18 at 19:35
  • 2
    One of many ways in which C++ differs from Java is that it has object slicing. Java avoids it because all references behave in a way similar to pointers of C++. Look up "object slicing" for more information. – Sergey Kalinichenko Feb 06 '18 at 19:36
  • 2
    You have a vector of base-class object only. Whenever you push an object of a child-class you have [*object slicing*](http://stackoverflow.com/questions/274626/what-is-object-slicing). For polymorphism to work you need either references or pointers. – Some programmer dude Feb 06 '18 at 19:36
  • 1
    Using a `std:;vector` of base class object types causes a problem known as object slicing in C++. Look up "object slicing" here at SO as well as the wider net. – R Sahu Feb 06 '18 at 19:36
  • ok thank you guys. I will read about this. – Piotr Skorupa Feb 06 '18 at 19:53

2 Answers2

1

As mentioned, you ran into slicing as you only store the Monster part of all objects in the vector. You can either use std::vector<Monster*> or, since c++11 std::vector<std::unique_ptr<Monster>>, to store pointers/unique_ptr to Monster in your vector. Storing a pointer to the actual object mitigates slicing as the object is not stored directly in the vector but only a reference to the actual object on the heap, like it is done it Java by default.

If you really need value-semantics, you should have a look at boost.polycollection but this is a rather advanced topic IMHO.

An Ky
  • 113
  • 11
0

Thanks for your answers. I can't add you points for help because, I am new on "stack" . I read about this problem and i wrote a solution. If someone need this.

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


class Monster
{
public:
    virtual void describe() {};
    virtual std::unique_ptr<Monster> copy_class()
    { 
        return std::unique_ptr<Monster>(std::make_unique<Monster>()); 
    }

};

class Skeleton : public Monster 
{
protected:
    const int life = 100;
public:
    Skeleton() {

    }
    ~Skeleton(){}
    void describe() override final {
        std::cout << "I am skeleton" << std::endl;
    }
    std::unique_ptr<Monster> copy_class() override 
    { 
        return std::unique_ptr<Monster>(std::make_unique<Skeleton>()); 
    }
};


class Zombie : public Monster
{
public:
    Zombie(){}
    ~Zombie(){}
    void describe() override {
        std::cout << "I am zombie" << std::endl;
    }
    std::unique_ptr<Monster> copy_class() override
    { 
        return std::unique_ptr<Monster>(std::make_unique<Zombie>());
    }
};


class UpgradeSkeleton final: public Skeleton
{
public:
    UpgradeSkeleton(){}
    ~UpgradeSkeleton() {}
    std::unique_ptr<Monster> copy_class() override { return std::unique_ptr<Monster>(std::make_unique<UpgradeSkeleton>()); }
};

int main(void) {

    std::vector<std::unique_ptr<Monster>> monsters;

    Skeleton s;
    Zombie z;
    UpgradeSkeleton us;

    monsters.push_back(std::unique_ptr<Monster>(s.copy_class()));
    monsters.push_back(std::unique_ptr<Monster>(z.copy_class()));
    monsters.push_back(std::unique_ptr<Monster>(us.copy_class()));



    for (auto &p : monsters) {
        p->describe();
    }

    std::cin.get();
    return 0;

}