C ++: interface providing copy-constr definition

Is there a way for an interface class to apply the definition of a copy constructor and possibly other constructors? In my case, I have a pure abstract IResource class, and I want all classes that implement this interface to define copy-constr, a constructor for loading from a file, and a constructor for loading from memory.

+6
source share
4 answers

To build an object, you need to know the specific class to use (how else would you know how much memory is allocated, which virtual table to use, etc.?). Thus, the interface does not work when working with designers, and you cannot use interfaces (pure virtual machines) to ensure the existence of such a designer. Naturally, when you think about it, virtual machines only work when you have a polymorphic object, i.e. After creating the instance. Anyone referencing your IResource interface will only deal with object instances and will never touch the constructor.

You can apply these restrictions to things using templates if you want. Just by calling the copy constructor from the template function, the compiler will complain if it encounters instantiating the template using a type that does not have a copy constructor.

+5
source

You cannot provide this, and it will not be right either. On the contrary, you should prohibit the use of public copy constructors in the hierarchy of polymorphic classes ...

 struct IResource { virtual IResource* Clone() const = 0; virtual ~IResource() {} }; 

The IResource should follow this pattern:

 class ConcreteResource : public IResource, public boost::noncopyable { // or equivalent public: virtual ConcreteResource* Clone() const; explicit ConcreteResource(std::string const & pString) : mString(pString) {} private: std::string mString; }; ConcreteResource* ConcreteResource::Clone() const { return new ConcreteResource(this->mString); } 
+1
source

Something in your project uses the abstract IResource class, and for some reason I doubt that it requires that the objects used contain specific constructors.

Something else is creating IResource objects (maybe a lot of things), and for this it must use a constructor. The concrete classes that are created must implement the necessary constructors or the code will not compile.

So, the answer to your question is that you ensure the presence of constructors by using these constructors in some other code to create objects. Keep in mind that if constructors are not used anywhere, they are not needed.

0
source

you can put forward all the requirements for resource implementations as follows:

 class t_resource_interface { protected: virtual ~t_resource_interface(); public: virtual t_serialization* serializeResource() = 0; virtual t_thing* cloneResource() = 0; }; /* type disambiguators */ typedef enum t_load_from_url { LoadFromURL = 0 } t_load_from_url; typedef enum t_load_from_memory { LoadFromMemory = 0 } t_load_from_memory; typedef enum t_copy_constructor { CopyConstructor = 0 } t_copy_constructor; template < typename TResourceImplementation > class t_resource : public t_resource_interface { public: /* copy ctor should generally be avoided due to the expense. introduce a parameter for those cases where it really needed and disable the standard copy ctor */ t_resource(const t_copy_constructor& copyCtor, const t_resource& other) : t_resource_interface(), d_implementation(TResourceImplementation::CopyConstructor(other.d_implementation)) { MONUnusedParameter(copyCtor); } t_resource(const t_load_from_url& fromFile, const t_url& url) : t_resource_interface(), d_implementation(TResourceImplementation::LoadFromURL(url)) { MONUnusedParameter(fromFile); } t_resource(const t_load_from_memory& fromMemory, const t_serialization& serialization) : t_resource_interface(), d_implementation(TResourceImplementation::LoadFromMemory(serialization)) { MONUnusedParameter(fromMemory); } virtual ~t_resource() { } public: /* t_resource_interface requirements. implementation forwarded to TResourceImplementation */ virtual t_serialization* serializeResource() { return this->d_implementation->serializeResource(); } virtual t_thing* cloneResource() { return this->d_implementation->cloneResource(); } private: /* assuming you will end up needing dynamic allocation/polymorphism along the way... */ t_auto_pointer<TResourceImplementation> d_implementation; private: /* prohibited */ t_resource(const t_resource&); t_resource& operator=(const t_resource&); }; class t_image_resource_implementation : public t_resource_interface { private: static t_image_resource_implementation* ValidationCheck(const t_image_resource_implementation* const arg) { assert(arg && "allocation or argument error"); if (0 == arg) { return 0; } else if (0 == arg->isValid()) { delete res; return 0; } else { return arg; } } public: static t_image_resource_implementation* CopyConstructor(const t_image_resource_implementation* const other) { return ValidationCheck(new t_image_resource_implementation(other, ...)); } static t_image_resource_implementation* LoadFromURL(const t_url& url) { /* assuming t_image_at_url_resource_implementation exists */ return ValidationCheck(new t_image_at_url_resource_implementation(url, ...)); } static t_image_resource_implementation* LoadFromMemory(const t_serialization& serialization) { assert(serialization); if (0 == serialization) { return 0; } else { return ValidationCheck(new t_image_resource_implementation(serialization, ...)); } } /* some physical ctors and the rest of the implementation... */ public: /* t_resource_interface requirements */ virtual t_serialization* serializeResource() { return this->createSerialization(); } virtual t_thing* cloneResource() { return this->clone(); } }; typedef t_resource<t_image_resource_implementation> t_image_resource; t_error_code ConvertImageToGrayscale(const t_url& sourceUrl, const t_url& destinationUrl) { t_image_resource imageResource(LoadFromURL, sourceUrl); /* ... */ } 
0
source

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


All Articles