【问题标题】:Storing derived class to the vector C++将派生类存储到向量 C++
【发布时间】:2021-11-22 10:36:08
【问题描述】:

我在将子类对象存储到向量时遇到问题。我有父类

class IngameObject
{
protected:
    bool clickable = false;
};

我有二等课

class Character : public IngameObject
{
protected:
    bool clickable = true;
};

现在,我正在尝试创建 Character 的新实例并将其添加到向量中。我将向量定义为

std::vector<IngameObject*> objVector;

创建字符和存储字符的代码是

for(int i = 0; i < 1; i++)
{
     int a = i*32;
     Character *c = new Character(this->holderTextures["texture"], sf::IntRect(a, a, 32, 32), sf::Vector2f(2*a, 10.f));
     std::cout << instanceof<Character>(c) << " TEST" <<std::endl;
     this->objVector.emplace_back( c );
     std::cout << instanceof<Character>(this->objVector.back()) << " TEST" <<std::endl;
}

在第一种情况下,实例是字符。在 emplace_back 到 objVector 之后是实例 IngameObject 的类型,并且 bool clickable 设置为 false。我做错了什么?

编辑 Instanceof 定义为

template<typename Base, typename T>
inline bool instanceof(const T*) {
   return std::is_base_of<Base, T>::value;
}

【问题讨论】:

  • 什么是instanceof
  • 已添加到帖子中。 :)
  • 另请注意,Character两个 变量,名为 clickableCharacter::clickableIngameObject::clickable。默认构造函数会将前者设置为true,将后者设置为false。如果您尝试访问foo-&gt;clickable,其中fooIngameObject* 指针,它只会查看IngameObject::clickable。与其声明一个新的成员变量,不如编写一个 Character 构造函数来正确设置继承变量的值。
  • instanceof&lt;Character&gt;(this-&gt;objVector.back()) 将始终为false,无论objVector.back() 是否恰好指向CharacterobjVector.back()IngameObject*,这意味着您正在检查std::is_base_of&lt;Character, IngameObject&gt;::value,即false。如果你想runtime检查实际指向的对象是否是Character的实例,你需要做一个dynamic_cast
  • 您的ingameObject 缺少虚拟析构函数,因此以多态方式使用是不安全的。

标签: c++ object inheritance vector


【解决方案1】:

将派生类存储在std::vector 中是正确的:问题与多态性或“将派生类存储在向量中”无关:

#include <iostream>
#include <vector>

class IngameObject
{
protected:
    bool clickable = false;
};

class Character : public IngameObject
{
protected:
    bool clickable = true;
};

int main()
{
    std::vector<IngameObject*> objVector;
    
    Character *c = new Character();
    objVector.emplace_back( c );
    
    delete c;

    return 0;
}

问题与你实现instanceof有关


要解决instanceof 函数,您的类需要是多态的。然后,可以将指向基类的指针转换为派生类,从而确认是instanceof基类:

#include <iostream>
#include <vector>

class IngameObject
{
protected:
    bool clickable = false;
    virtual ~IngameObject() = default;
};

class Character : public IngameObject
{
protected:
    bool clickable = true;
};

template<class T, class U>
inline bool instanceof(U* ptr) {
   return nullptr != dynamic_cast<T*>(ptr);
}


int main()
{
    std::vector<IngameObject*> objVector;
    
    Character *c = new Character();
    std::cout << instanceof<Character>(c) << " TEST" <<std::endl;
    objVector.emplace_back( c );
    std::cout << instanceof<Character>(objVector.back()) << " TEST" <<std::endl;
    
    delete c;

    return 0;
}

注意:要使Base具有多态性,它至少需要有一个虚方法。

【讨论】:

  • 答案如何?
  • 它展示了如何将派生类存储在向量中。同时,我正在尝试解决它的“instanceof”功能。
  • 在您的instanceof() 中,Base 参数具有误导性,因为这是正在测试的 派生 类型。我会改用这个:template&lt;class T, class U&gt; inline bool instanceof(U* u) { return nullptr != dynamic_cast&lt;T*&gt;(u); }
  • 已修复!我试图尽可能少地更改他的代码,但我 100% 同意你的建议。
猜你喜欢
  • 2019-05-13
  • 2015-08-11
  • 2018-09-17
  • 2018-01-27
  • 1970-01-01
  • 2017-02-06
  • 2013-03-28
  • 2013-03-27
  • 1970-01-01
相关资源
最近更新 更多