简体   繁体   English

在矢量中存储各种类型

[英]Storing various types in a vector

I'm trying to store various different types of data in an array or vector. 我试图在数组或向量中存储各种不同类型的数据。 So far I'm doing this by using a base class that will be stored in the vector as pointers to each object and then type casting to get the data back. 到目前为止,我通过使用一个基类来实现这一点,该基类将作为指向每个对象的指针存储在向量中,然后键入强制转换以获取数据。 This works great for int, but any other type of data throws a access violation exception. 这适用于int,但任何其他类型的数据都会引发访问冲突异常。

Sorry if my explanation isn't very good, here is my code with comments that I hope will help: 对不起,如果我的解释不是很好,这是我的代码和评论,我希望将有所帮助:

//Base class
class MenuProperty
{
private:
    std::string Name;

public:
    MenuProperty(std::string Name) : Name(Name) {};
    ~MenuProperty() {};

    std::string GetName();

};

//Typed class used to store data
template<class T>
class TMenuProperty : public MenuProperty
{
private:
    T Data;

public:
    TMenuProperty(std::string Name, T Data) : MenuProperty(Name), Data(Data) {};

    T GetData()
    {
       return this->Data;
    }
};

//Class with no type and data pointer to retrieve data
class cpMenuProperty : public MenuProperty
{
private:
    VOID* Data;

public:
    cpMenuProperty(std::string Name) : MenuProperty(Name) {};

    VOID* GetPointer()
    {
       return this->Data;
    }
};

Hope that makes some semblance of sense, here is my test code: 希望有一些相似之处,这是我的测试代码:

int main()
{
    TMenuProperty<double> fP("Test2", 33.7354); //Create instance of property

    MenuProperty* fMP = &fP;                    //Make a pointer to the object

    cpMenuProperty* Test;                       //Make a pointer to the retrieving
                                                //object

    std::vector<MenuProperty*>              Vec;
    std::vector<MenuProperty*>::iterator    it;

    Vec.push_back(fMP);                         

    it = Vec.begin();

    Test = static_cast<cpMenuProperty*>(*it);   //Cast the first object in the list 
                                                //list to the same type as the
                                                //retrieveing object


    double Data = *(double*)Test->GetPointer(); //Dereference and access, this is
                                                //where the exception is thrown

    std::cout << Data;



    int Ret;
    std::cin >> Ret;
}

I'm probably making some monumental error here, but thank you for taking the time to read it thus far :) Any help is appreciated, and constructive criticism too! 我可能在这里犯了一些巨大的错误,但是感谢你花时间阅读它到目前为止:)任何帮助都是值得赞赏的,也是建设性的批评!

You're initializing a TMenuProperty object on the stack, which you're then casting to a cpMenuProperty. 您正在初始化堆栈上的TMenuProperty对象,然后将其转换为cpMenuProperty。 There is never any memory allocated for the void* Data in the cpMenuProperty. 永远不会为cpMenuProperty中的void * Data分配任何内存。 There is no relationship between TMenuProperty and cpMenuProperty, except that they're derived from the same class. TMenuProperty和cpMenuProperty之间没有任何关系,除了它们来自同一个类。 This design is never going to work. 这种设计永远不会起作用。

  • Get rid of all of the void*'s. 摆脱所有的空虚*。 That's asking for trouble. 那是在惹麻烦。
  • Don't use static_cast<> unless you 100% know what you're doing. 除非你100%知道你在做什么,否则不要使用static_cast <>。 Use dynamic_cast, it would have told you that the conversion isn't valid (I'm guessing that you tried this but then fell back to static_cast to force the code to at least compile :) ) 使用dynamic_cast,它会告诉你转换是无效的(我猜你试过这个,但后来回到static_cast强制代码至少编译:))
  • Why don't you use TMenuProperty all the way? 你为什么不一直使用TMenuProperty? That approach should work. 这种方法应该有效。
  • For other ways of doing what you're after, look at boost::variant and boost::any. 对于你正在做的事情的其他方式,请看boost :: variant和boost :: any。
  • If you're brave and really know what you're doing (no offense, but I don't think you qualify for this), and if the data type you need to wrap is uniform enough in terms of memory layout, you could maybe make your code work with proper memory padding settings and forcing memory alignments in a certain way. 如果你是勇敢的并且真的知道你在做什么(没有冒犯,但我认为你没有资格获得这个),如果你需要包装的数据类型在内存布局方面足够统一,你可以使您的代码使用适当的内存填充设置并以某种方式强制进行内存对齐。 However I can't come up with any scenario, no matter how unlikely, to find a reason to do it like that. 但是,无论多么不可能,我都无法想出任何理由来找到这样的理由。 So from what I can tell from this post, I can only advise to remove cpMenuProperty and work with the abstract base class / templated derived class approach only. 所以从我在这篇文章中可以看出,我只能建议删除cpMenuProperty并仅使用抽象基类/模板化派生类方法。
 #include<iostream>
 #include<vector>
 #include<iterator>
 #include<memory>
 class base {
 public:
 virtual void foo(){
      std::cout << "in base" << std::endl;
  }
 };

 class derived : public base {
 public:
 virtual void foo(){
      std::cout << "in derived" << std::endl;
   }
 };

 int main()
 {
    std::vector<std::unique_ptr<base>> vec;
    vec.emplace_back(new derived);
    static_cast<derived*>(vec[0].get())->foo();
    return 0;
  }

classic example, using modern practices. 经典的例子,使用现代实践。

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

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