0

In Java I can instantiate an object using the 'Class' method 'newInstance' which for my particular system I find very helpful indeed. I am now trying to achieve something similar in C++.

It has not been obvious to me how this might be achieved but after some reflection .... (do you get it ... huh?) I think that it might be possible by creating a ClassDescription class which has an attribute holding the 'sizeof' the class instance and a method newInstance which mallocs this amount of memory and returns it as a void *. The calling code will then need to cast this appropriately.

Does the C++ language suitably define whether this is valid?

By the way .. I recognise that I could create a registry holding Factories for the classes which is a backup plan. For answers to this question I would value focusing on the specific question of whether what I have discussed will work.

Best Regards

* Additional Context * The reason for this requirement is to allow a generic library to instantiate classes which the library user is aware of but not the library itself. The library will have some meta data to use to achieve this and so could be told the sizeof the class. It is 'neater' from the user perspective not to have to add a factory object to the the meta data.

Howard May
  • 6,639
  • 9
  • 35
  • 47
  • 1
    Why don't you just give your class a private constructor and call `new Class` from a static method? Don't use malloc, it won't call the classes constructor for you. – Benj May 08 '12 at 09:49
  • Are you asking why `malloc` is not used to allocate object instances in C++? – Cody Gray - on strike May 08 '12 at 09:50
  • If you want to go down this route then you should look into [placement new](http://stackoverflow.com/questions/222557/cs-placement-new) – tinman May 08 '12 at 09:50
  • @Benj Unfortunately the calling library does not know the classes it needs to instantiate. – Howard May May 08 '12 at 10:13
  • @Cody No, rather I am asking whether it is possible to do this. – Howard May May 08 '12 at 10:14
  • To expand Benj's answer, instead of passing the sizeof of a class to the library, pass function pointers to static members of the class that use `new`. – Skizz May 08 '12 at 11:31
  • You're going to have to add an object of some sort to store the size information etc., instead of storing the size in that object why not just store a `std::function` that handles the creation. – Flexo May 08 '12 at 11:36

3 Answers3

4

This would be valid in some instances. The requirement is that the type must be a "plain old data type" (POD) (see also this answer). If it has anything more complicated (e.g. virtual member functions, members which have virtual member functions, base classes must also be POD etc.) then it will not work and is undefined behaviour.

You can check if a type meets these requirements by doing:

#include <type_traits> 

static_assert(std::is_pod<A>::value, "A must be a POD type.");

In general though it probably indicates that you're doing it wrong. C++ isn't Java and there's probably a much better way to solve the underlying real problem.

Community
  • 1
  • 1
Flexo
  • 87,323
  • 22
  • 191
  • 272
  • your link says that `type_traits` is c++11 ... in that case, it will limit the usefulness of this approach... – user1055604 May 08 '12 at 10:13
  • @user1055604 - boost has a `is_pod`, but its usefulness is somewhat limited pre-C++11 IIRC. You can always do it without the assert if you're willing to make that bet on your own. And MSVC and recent GCC as well as clang all support this. It's also in TR1 I believe, which pre-dates C++11 somewhat. This answer lists the requirements for this type of behaviour to be legal and shows how you can verify they've been met in code. – Flexo May 08 '12 at 10:17
2

What you're missing in the malloc and cast method is the construction of the object. Using new both allocates memory and constructs it. This includes building v-tables, calling the constructor and so on. Type casting malloc allocated memory is not valid.

Skizz
  • 69,698
  • 10
  • 71
  • 108
0

Note that mallocing a memory block of the right size gives you just raw memory. You need to construct an object of the desired class in this memory block. This can be achieved using placement new.

Péter Török
  • 114,404
  • 31
  • 268
  • 329