Search code examples
c++classoopderived

Obtain variable from derived class c++


I'm looking to do something only if the class is a specific derived class. That is I have:

class X{
    int id;
}

class A: public X{
    void run();
}

class B: public X{
    int lala;
}

And I want to do something along the line of:

main(){
    vector<X *> types;
    types.push_back(new A);
    types.push_back(new B);
    int var = 0;
    for(int i = 0; i<types.size(); i++){
        if(types[i].isType(A)) {types[i].run();} 
    }
    for(int i = 0; i<types.size(); i++){
        if(types[i].isType(B)) {var = lala;} 
    }
}

I do not want class B to have anything equivalent to run(), nor do I want class A to have an equivalent to lala.

I know fortran has a workaround with

select type ( x => var )
class is ( A )
    x.run()
end select

But I wasn't sure what my options in C++ were.

Thanks


Solution

  • You are looking for dynamic_cast.

    #include <vector>
    using namespace std;
    
    class X {
    public:
        int id;
        virtual ~X() = default;
    };
    
    class A : public X {
    public:
        void run() {}
    };
    
    class B : public X {
    public:
        int lala;
    };
    
    main(){
        vector<X *> types;
        types.push_back(new A);
        types.push_back(new B);
        int var = 0;
        for(int i = 0; i<types.size(); i++){
            if (auto ta = dynamic_cast<A *>(types[i])) {
                ta->run();
            }
        }
        for(int i = 0; i<types.size(); i++){
            if (auto tb = dynamic_cast<B *>(types[i])) {
                var = tb->lala;
            }
        }
    }
    

    Also see it in action here: https://onlinegdb.com/B1d29P5if.

    I had to fix a few other problems with the code. Since they are not a part of your question, I won't clarify here, but you are welcome to ask if something is not clear.

    EDIT: The above solution has memory leaks, which I didn't fix, as it wasn't required by the question. For completeness, here is the main function with memory leaks fixed (https://onlinegdb.com/ByeOmu9iz):

    int main() {
        vector<unique_ptr<X>> types;
        types.emplace_back(new A);
        types.emplace_back(new B);
        int var = 0;
        for(int i = 0; i < types.size(); ++i) {
            if (auto ta = dynamic_cast<A *>(types[i].get())) {
                ta->run();
            }
        }
        for(int i = 0; i < types.size(); ++i) {
            if (auto tb = dynamic_cast<B *>(types[i].get())) {
                var = tb->lala;
            }
        }
    }
    

    Note that this is a C++11 solution.

    If you're working with an even older compiler, you'll have to keep using plain pointers as in the original solution, and deallocate the memory manually at the end by calling delete on each element of the vector. (And hope nothing throws an exception before you reach that step.) You'll also have to replace auto ta with A* ta and auto tb with B* tb.