Best way to create a shared object in C ++?

Having mainly requested in C #, I am at a loss when it comes to C ++. However, I need to create a C ++ application because it is just a component in a larger C ++ solution.

Situation

  • I have a structure (parent) that includes a data component (object). It can be a data component of any type — for example, a custom structure.
  • Only the parent compiler (who created the object of the parent object), and the final receiver must know the type of the data component inside the object, since the data refers only to them.
  • The parent structure, however, can go through several methods, objects, and even other processes.
  • The data parameters for the object are limited, and both the compiler and the decompiler know different options for data types. Consequently, they can decompile the object in its original form.
  • However, types can be extended (i.e. limited, this is not necessarily fixed), and the decompiler and compilers will be updated in the future.

Problem - I do not want to recreate every method and object that may encounter this data component with a “template” ... also seeing that the data type may be changed in the future, they suggested that templates for each process that encounter an object in the end result is not ideal for a start.

I searched for something similar to a C # object - and wrote the following components

Question

  • This is a good solution or I may run into problems in the future.
  • Are there any improvements that could be made about this? About what I did not think about (especially in order not to include Object \ impl.h?
  • Is there a completely different / better solution?

Code

  • I have the following in the header file

    struct Object { Object(); // Return true if value has succesfully been set // Return false if there is no compatibility between Value and result. template <typename T> bool GetValue(T &result); template<typename T> bool SetValue(T value); virtual LPVOID GetObjectAddress() = 0; virtual const char* GetType() = 0; }; template<typename T> struct ObjectType:public Object { ObjectType(T value); T Value; LPVOID GetObjectAddress(); const char* GetType(); }; 

I also have a CreateType function to create several ready-made objects at startup, and for example, the target is called as follows at the end of the .h file.

  template class CreateType<int>; 

Remember that int is, for example, ... in fact, these are different structures.

  • I also have another header file which is at the bottom of this header file as follows:

     #include "Implementation\Object_impl.h" -> looks like this template<typename T> ObjectType<T>::ObjectType(T value) { Value = value; }; template <typename T> // Return true if value has succesfully been set // Return false if there is no compatibility between Value and result. bool Object::GetValue(T &result) { if (typeid(result).name() == GetType()) { result = *(T *)GetObjectAddress(); return true; } return false; }; template<typename T> bool Object::SetValue(T value) { if (typeid(T).name() == GetType()) { *(T*)GetObjectAddress() = value; return true; } return false; }; template<typename T> const char* ObjectType<T>::GetType() { return typeid(Value).name(); } template<typename T> EXPOBJ LPVOID ObjectType<T>::GetObjectAddress(){ return (LPVOID)&Value; } 

I would like to include most of this in the cpp file, but then I could not create another object on demand ... I’m not sure what the consequences will be ... also expand the types you just need to include the regular header file of the object.

I know inline might be an option, but also think that it is not perfect?

This compiles at the moment and works great as a “generic” option. Can it also be extended, inheriting from inheritance from "Object"?

... oh and use, I'm just doing this - which seemed to work:

  Object * a; a = new ObjectType<testing>(testing()); testing x = testing(); xi = 50; a->SetValue(x); testing y = testing(); testing &z = y; a->GetValue(z); cout << zi << " for z and y = " << yi << endl; Result -> 50 for z and y = 50 
+6
source share
1 answer

As a rule, we avoid anything remote, like the type of an object. If this is absolutely necessary (and it almost never happens), we use boost :: any.

As for your code: which is actually impressively good, but here's a bit, I would say:

You do not have a destructor. This is a BIG mistake.

 virtual ~Object() {} //and virtual ~ObjectType() {} 

In addition, GetObjectAddress not type safe.

 class Object { //stuff template<class T> T* GetObjectAddress(); private: virtual LPVOID GetRawPointer() = 0; }; template<class T> inline T* Object::GetObjectAddress() { if (typeid(T).name() == GetType() || typeid(T).name()==typeid(void).name()) { return static_cast<T*>(GetRawPointer()); } return nullptr; } 

In addition, I would prohibit copying and moving destination bits, which helps prevent errors.

 class Object { Object(const Object&) = delete; Object(Object&&) = delete; Object& operator=(const Object&) = delete; Object& operator=(Object&&) = delete; //stuff }; 

I would give the derived type a default constructor, and conversion constructors

 template<typename T> struct ObjectType:public Object { ObjectType() {} //C++11 here: template<class...Ts> ObjectType(Ts...Vs) :Value(std::forward<Ts>(Vs)...) {} //C++03 here: template<class first> ObjectType(const first& f) : Value(f) {} template<class t0, class t1> ObjectType(const t0& p0, const t1& p1) : Value(p0, p1) {} template<class t0, class t1, class t2> ObjectType(const t0& p0, const t1& p1, const t2& p2) : Value(p0, p1, p2) {} //etc etc etc 

Finally, use smart pointers instead of raw ownership pointers. Source pointers are fine if they do not own what they point to.

 std::unique_ptr<Object> a; a.reset( new ObjectType<testing>() ); 
+7
source

Source: https://habr.com/ru/post/972424/


All Articles