【问题标题】:Access methods of subclass from an instance casted to a pointer to base class子类的访问方法从实例转换为指向基类的指针
【发布时间】:2018-04-17 15:12:44
【问题描述】:

我有两个类A 和B,它们派生自同一个基类Base。 我主要定义了一个向量Base *,我用它来存储A和B的元素。 使用 reinterpret_cast 我可以调用他们真实类的方法。 这段代码安全吗?有没有更好/标准的方法来做到这一点?

实际代码中的两个类共享基类的大部分方法,但A 拥有一些与Base 或B 不共享的方法,B 也是如此,因此 virtual 不是选项。

#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_cast:Can I get polymorphic behavior without using virtual functions?

这是答案吗?

【问题讨论】:

  • 给Base添加一个虚析构函数,使用dynamic_cast做向下转换,尽量不要向下转换。

标签: c++ polymorphism


【解决方案1】:

有没有更好/标准的方法来做到这一点?

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

  2. 如果你不能使用virtual成员函数,执行dynamic_cast,检查转换状态,只有转换成功才调用成员函数。

    李>

请注意,基类需要有一个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;
}

【讨论】:

  • 使用 dynamic_cast 我得到错误 'Base' is not polymorphic
  • @Nisba,基类需要有一个virtual 成员函数才能使dynamic_cast 工作。在这种情况下,建议至少将析构函数设为virtual 成员函数。
  • 效果很好!额外的问题:它是否也适用于智能指针?
  • 我发现有一个标准的方法可以做到这一点:en.cppreference.com/w/cpp/memory/shared_ptr/pointer_cast
  • @Nisba,是的,它可以与智能指针一起使用,正如您已经弄清楚的那样。
猜你喜欢
  • 2015-08-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-11
  • 1970-01-01
  • 1970-01-01
  • 2017-04-13
相关资源
最近更新 更多