简体   繁体   中英

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.

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. There is never any memory allocated for the void* Data in the cpMenuProperty. There is no relationship between TMenuProperty and cpMenuProperty, except that they're derived from the same class. 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. 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 :) )
  • Why don't you use TMenuProperty all the way? That approach should work.
  • For other ways of doing what you're after, look at boost::variant and 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.
 #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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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