Handle a class in C ++?

In C ++ Prime 15.8, when the author talked about "class and inheritance," he said:

'A common technique in C ++ is to define what is called a cover class or handle. The handle class stores and manages a pointer to the base class. The type of object this pointer points to will differ; it can point to a base or derived type object. Users access inheritance hierarchy functions through a descriptor. Since the descriptor uses its pointer to perform these operations, the behavior of virtual members will change at run time depending on the type of object to which the descriptor is actually attached. This way, descriptor users get dynamic behavior, but they don’t have to worry about pointer management.

The above sounds a lot like a smart pointer to me. However, the use of this “pen” is slightly different.

Handle h(Derived()); // noticed a derived object, not a pointer is used to initialize the handle! h->func(); 

And the last implementation of the descriptor (shown below) proves that the author comments on the descriptor: “We would like users of our descriptor to create their own objects to which they can attach the descriptor. The descriptor will select a new object of the appropriate type and copy the user object into this newly selected object . Thus, the class handle will have an object and can guarantee that the object will not be deleted until the last handle attached to the object disappears. '

 public: Base(){} virtual int func(std::size_t n) const {} virtual Base* clone() const { return new Base(*this); } }; class Derived : public Base { public: Derived():Base(){} int func(std::size_t) const; // redefine Derived* clone() const { return new Derived(*this); } }; class Handle { public: Handle(const Base &b):p(b.clone()), use(new std::size_t(1)) { } private: Base *p; std::size_t *use; // pointer to shared use count }; 

My question is: is this really the typical descriptor meaning in C ++ or OO? I thought that the descriptor could be just an intelligent pointer of a base type that contains the inside of the use or, as a rule, some type of magic type that the system knows what it points to and what to do with it. Why is it needed here to make a copy of the user object to itself, and then use a counter-based copy?

Does anybody help?

Thanks,

+4
source share
1 answer

The idiomatic equivalent in modern C ++ would be:

 std::shared_ptr<Base> h{std::make_shared<Derived>()}; 

In general, a “descriptor” implies some form of type erasure, so the code associated with the descriptor does not need details on how the functionality is implemented.

The reason that the code you showed uses clone to copy an object precisely in order to erase styles; at the point where the clone method is called knowing the actual type of the Derived object, it is erased. As for the quality of implementation, the code is not thread safe, which is not related to obsolete C ++, but the problem is for modern C ++, which has a memory model with thread support. This also does not exclude exceptions; it is much better to delegate exception safety to standard library classes such as shared_ptr . Finally, there is no virtual destructor in the Base class.

+4
source

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


All Articles