简体   繁体   中英

Access methods of subclass from an instance casted to a pointer to base class

I have two classes A and B which derive from the same base class Base . I am defining in main a vector Base * and I use it for storing elements both of A and B . Using a reinterpret_cast I am able to call methods of their real class. Is this code safe? Is there a better/standard way of doing that?

The two classes in the real code share most of the methods from the base class but the A possesses some methods not shared with Base or B and the same for B , so virtual is not an option.

#include <iostream>
#include <vector>

class Base {
};

class A : public Base {
public:
    void print_from_A() {
        std::cout << "hello from A\n";
    }
};

class B : public Base {
public:
    int number;
    void read_from_B() {
        std::cin >> number;
    }
};

int main(int argc, char * argv[]) {
    std::vector<Base*> v;
    v.push_back(new A());
    v.push_back(new B());

    (reinterpret_cast<A *>(v[0]))->print_from_A();
    (reinterpret_cast<B *>(v[1]))->read_from_B();

    for(auto && e: v) {
        delete e;
    }
    return 0;
}

EDIT:

It seems that using reinterpret_cast is undefined behaviour: Casting to one class and calling function from sibling class?

It also seems that the correct way is using a static_cast : Can I get polymorphic behavior without using virtual functions?

Is this the answer?

Is there a better/standard way of doing that?

  1. It is better to use a virtual member function.

  2. If you are not able to use a virtual member function, perform a dynamic_cast , check the status of the cast, and call the member function only if the cast succeeds.

Please note that the base class needs to have a virtual member function for dynamic_cast to work. In such cases, it is is recommended to make at least the destructor a virtual member function.

Here's an updated version of your program using virtual member functions:

#include <iostream>
#include <vector>

class Base {
   public:
      virtual ~Base() {}
      virtual void print() const = 0;
      virtual void read() = 0;
};

class A : public Base {
public:
    virtual void print() const {
        std::cout << "hello from A\n";
    }
   virtual void read() 
   {
      // Nothing to do.
   }
};

class B : public Base {
public:
    int number;
    virtual void print() const {
        std::cout << "hello from B, " << number << "\n";
    }
    virtual void read() {
        std::cin >> number;
    }
};

int main(int argc, char * argv[]) {
    std::vector<Base*> v;
    v.push_back(new A());
    v.push_back(new B());

    v[0]->read();
    v[0]->print();
    v[1]->read();
    v[1]->print();

    for(auto && e: v) {
        delete e;
    }
    return 0;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM