How do you pass an unknown object into a function and save it? I'm trying to have a set and get function in a class I'm creating that can hold and return any object.

Here are my attempts so far:

void* holder;

void setHolder(void* object)
{
  holder = object;
}

void* getHolder()
{
  return holder;
}

OR

void setHolder(void* &object)
{
  holder = object;
}

void* getHolder()
{
  return holder;
}

I'm also unsure how I would enter the object into the function if one of these are correct.

ex. 
Object object();

myClass.setHolder(&object); ?
or
Object* ptr = object;
myClass.setHolder(ptr); ?

Thanks for any help.

Recommended Answers

All 4 Replies

Quick note: I'm looking for behavior similar to using the object keyword in C#

This:

void* holder;

void setHolder(void* object)
{
  holder = object;
}

void* getHolder()
{
  return holder;
}

And this:

Object someObject = new object();

someObject.setHolder(&object);?

Would be the correct way to do it.
There is no way to do dynamic binding in C++ without using a void* pointer that I am aware of, so there is no equivalent to C#'s object datatype in C++.

PS: You may want to test that on your own because last time I used C++ was like a year ago :).

>>How do you pass an unknown object into a function and save it?
It all depends on how "unknown" the object is. There is a big difference between "it could be one of a few different types" and "it could be of absolutely any type that exists or will ever be created". In either case, the solutions you posted are probably the worst, and that is because C++ is a strongly typed language and there is a good reason why that is... breaking type-safety with a cast to void* is always the very last resort (and very rarely needed in pure C++, if ever).

If it is of only a small number of possible types, you can use a union type. Say you could store an int, a double or a char, Then you could do this:

class MyClass {
  private:
    union value_type {
      char c;
      int i;
      float f;
    };
    value_type data; //data will hold any of the union's member types.
  public:
    //just let type-safe overloading work its magic:
    void set(char value) { data.c = value; };
    void set(int value) { data.i = value; };
    void set(float value) { data.f = value; };
    void get(char& result) { result = data.c; };
    void get(int& result) { result = data.i; };
    void get(float& result) { result = data.f; };
};

If you have more complex types, you can still use the same mechanism: use a union to store any of the types you are expecting and use parameter-type overloading of get/set functions to select the appropriate type of data. You can use this for pointers too, but be aware of pointers that are implicitly castable to other pointer types.

Another very good solution is to have a base class for all the different types you might want to hold. Then, just hold that base class pointer. However, you will have to use dynamic casting to cast the data back from a base class pointer to a derived class pointer:

class MyClass {
  private:
    BaseClass* data;
  public:
    template <class T>
    void set(T* aData) { data = aData; };
    template <class T>
    void get(T*& aData) { aData = dynamic_cast<T*>(data); };
};

NOTE: This is exactly what C# object is. It is just a base class for every single type in the whole C# language, and since everything is held by reference, it is equivalent to using a base class pointer in C++, except that you have to make the base class yourself.

The third solution, and the best IMO, is to use templates a lot (basically generic programming). But this would require more knowledge about your problem.

Also, note that Boost.Variant and Boost.Any might be good for you to look at. Here is an example with Boost.Any:

class MyClass {
  private:
    boost::any data;
  public:
    template <class T>
    void set(const T& value) { data = value; };
    template <class T>
    void get(T& result) { result = boost::any_cast<T>(data); }; 
};

There are definitely a plethora of solutions that are type-safe. If you can give more details about what this would be useful for to you, there would be more to say.

commented: exactly +7

The unknown type could be any type created by an App prgmr, so any type ever created would be a good description haha. Basically I want the set and get function to basically be a "wildcard" area to hold data for a class. It could anything from an integer to a struct or another class object.

The c# object is able to hold new data types created at compile time though, so that means it must be able to hold more than every type in the c# language? Or is it including the newly created object as another template when it compiles?

Vermillion, thanks that was the right combo, but mike I am open to better solutions. If possible, I'd like to avoid templates (unless simple) because I consider templates to be a major topic of their own that I don't have time to dive to much in before I need to finish this project.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.