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;

        }`
5
  • I'm a little confused by your question. Could you try to clarify what you need? Commented Feb 6, 2018 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. Commented Feb 6, 2018 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. For polymorphism to work you need either references or pointers. Commented Feb 6, 2018 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. Commented Feb 6, 2018 at 19:36
  • ok thank you guys. I will read about this. Commented Feb 6, 2018 at 19:53

2 Answers 2

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.

Sign up to request clarification or add additional context in comments.

Comments

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;

}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.