从实例转换为指向基类的指针的子类的访问方法

时间:2018-04-17 15:12:44

标签: c++ polymorphism

我有两个类AB,它们派生自相同的基类Base。 我在main中定义了一个向量Base *,我用它来存储AB的元素。 使用reinterpret_cast我可以调用他们真实类的方法。 这段代码安全吗?有没有更好/标准的方法呢?

真实代码中的两个类共享基类中的大多数方法,但A拥有一些未与BaseB共享的方法,而B则相同所以虚拟不是一种选择。

#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;
}

编辑:

似乎使用reinterpret_cast是未定义的行为:Casting to one class and calling function from sibling class?

似乎正确的方法是使用static_castCan I get polymorphic behavior without using virtual functions?

这是答案吗?

1 个答案:

答案 0 :(得分:1)

  

有更好的/标准的方法吗?

  1. 最好使用virtual成员函数。

  2. 如果您无法使用virtual成员函数,请执行dynamic_cast,检查强制转换的状态,并仅在投射成功时调用成员函数。

  3. 请注意,基类需要virtual成员函数才能使dynamic_cast正常工作。在这种情况下,建议至少使析构函数成为virtual成员函数。

    以下是使用virtual成员函数的程序的更新版本:

    #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;
    }