简体   繁体   English

指向包含基类和派生类 class 对象的指针的向量 - 访问派生类特定变量

[英]Vector of pointers to base class containing base and derived class objects - accessing derived-class specific variables

I've been struggling with with this C++ thing for a while.我一直在努力解决这个C++问题。 I've created base object class and derived object class and I'm trying to store references to both base and derived objects in a vector of base-class pointers (avoid object slicing).我已经创建了基类 object class 和派生类 object class 并且我试图将对基类和派生对象的引用存储在基类指针的向量中(避免 object 切片)。 With pointer, I am able to run virtual methods and I can confirm that pointer points to derived-class object, however I cannot get to derived class specific variables.使用指针,我可以运行虚方法,并且可以确认指针指向派生类 object,但是我无法获得派生类 class 的特定变量。 Is there any way of doing it?有什么办法吗?

Base class object:基地 class object:

class Base
{

public:

    Manager* manager;

    Base(){}
    Base(Manager* mManager){
        manager = mManager;
    }

    virtual void init(){}

    virtual void speak() {
        std::cout << "Base class is speaking!" << std::endl;
    }

};

Derived class object:导出 class object:

class Derived : public Base
{

public:

    Manager* manager;

    int DerviedVariable = 100;

    Derived(){}
    Derived(Manager* mManager){
        manager = mManager;
    }

    void speak() override {
        std::cout << "Derived class is speaking!" << std::endl;
    }

};

Those objects (Base na Derived) are created and stored using Manager class and array called groupedEntities:这些对象(Base na Derived)是使用Manager class和名为groupedEntities 的数组创建和存储的:


constexpr std::size_t maxGroups = 32;
using Group = std::size_t;

class Manager
{
public:

    std::array<std::vector<Base*>, maxGroups> groupedEntities;

    void addToGroup(Base* mBase, Group mGroup)
    {
        groupedEntities[mGroup].emplace_back(mBase);
    }


    std::vector<Base*>& getGroup(Group mGroup)
    {
        return groupedEntities[mGroup];
    }

    template <typename T, typename... TArgs>
    T* addEnt(TArgs&&... mArgs)
    {
        T* e(new T(this));
        return e;
    }

};

I am create objects and try to reference them like that:我正在创建对象并尝试像这样引用它们:

void main() {

    std:size_t groupBlob = 0u;

    Manager* manager = new Manager();
    Derived* blob1(manager->addEnt<Derived>());
    Derived* blob2(manager->addEnt<Derived>());


    manager->addToGroup(blob1, groupBlob);
    manager->addToGroup(blob2, groupBlob);


    auto& grouped(manager->getGroup(groupBlob));

    for (auto& e : grouped)
    {
        e->speak();
        std::cout << e.DerviedVariable ;

    }


}

Unfortunately, e.DerviedVariable is inaccessible, whereas speak() function says "Dervied class is speaking".不幸的是, e.DerviedVariable是不可访问的,而speak() function 说“Dervied class 正在说话”。 Is there any way to access Derived-class variables with this architecture?有什么方法可以用这种架构访问派生类变量吗? Thanks谢谢

Yes it is possible.是的,有可能。 You only need to cast the pointer.您只需要投射指针。 The simplest syntax is:最简单的语法是:

((Derived*)e)->DerviedVariable

which is equivalent (modulo casting away constness, if any) to C++ish这等同于 C++ish

static_cast<Derived*>(e)->DerviedVariable

The word “static” here reminds that there is no runtime checking: the compiler trusts you that e indeed points to an instance of Derived .这里的“静态”一词提醒您没有运行时检查:编译器相信您e确实指向Derived的一个实例。 If it doesn't, undefined behavior occurs.如果没有,则会发生未定义的行为。 The safer alternative is dynamic_cast :更安全的选择是dynamic_cast

Derived *ee = dynamic_cast<Derived*>(e);
if (ee)
    x = ee->DerviedVariable;

It returns NULL if the object is not an instance of Derived .如果 object 不是Derived的实例,它会返回 NULL。 (Note that references can be casted as well, but as there is no NULL reference, dynamic_cast will throw instead if cast is not possible) (请注意,也可以转换引用,但由于没有 NULL 引用,如果无法转换,则dynamic_cast将抛出)

Nevertheless, using such casts is often considered a bad practice, for a reason.然而,出于某种原因,使用此类转换通常被认为是一种不好的做法。 Virtual functions are preferable, mostly because using them don't require you to even know the actual object type at the call point.虚函数更可取,主要是因为使用它们不需要您甚至知道调用点的实际 object 类型。

You can use dynamic_cast in such cases.在这种情况下,您可以使用dynamic_cast The expression dynamic_cast<Derived*>(e) where e is of type Base* will evaluate to a Derived* if e does in fact point to an object of Derived type, otherwise it will evaluate to a null pointer.表达式dynamic_cast<Derived*>(e)其中eBase*类型,如果e实际上指向Derived类型的 object,则计算结果为Derived* ,否则它将计算为 null 指针。

if(Derived* d = dynamic_cast<Derived*>(e)) {
    std::cout << d->e.DerviedVariable;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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