📜 ⬆️ ⬇️

Once again about delegates in C ++

After reading the article “The simplest delegate in C ++”, I understood only that I did not understand absolutely nothing - tightly. Maybe this is because the author appealed in his thoughts to the concept of delegates in C #, which I know a little less than nothing. But I know Objective C, in which deligation is found quite often, and the approach to delegating there is not completely bad for C ++, and if people who write on it have a need for delegates, they might like this approach more. Immediately a reservation - since in object C, the linking of the object with the method takes place completely runtime, it will not work out all the same on the pluses, but here the great Straustrup left us a tiny slit - a table of virtual functions, so let's see through it.

First you need to clarify what is the approach to delegation in objective C.

So, according to the rules of a good tone, we should have an interface (@interface is a certain analogue of a class in pluses, further we will call it a class as well), and a protocol with declaration of delegate methods (@protocol), the class that needs to install delegates should have inheritance from it protocol (in the “kokoshnikov” language, support the protocol), and the class that causes delegates to have a pointer to a class with delegate methods and implemented protocol support (though, due to dynamic binding, inheritance is not necessarily - just copy-paste meta names If the protocol is needed by the required class, we define what to do - the compiler will show warning, but everything works, but in C ++ it will not work, then you need to follow everything written above earnestly.

Now go to the code. To begin, let's announce a pair of a similar protocol / interface, but with the amendment to the fact that we have C ++;
// SomeInterfaceAndProtocol.hpp #ifndef demo_interface_protocol #define demo_interface_protocol struct _protocol //   objC,      ,        { void virtual ActionString(char *)=0;// ; int virtual ActionRetNums(double S)=0; int virtual length(char *)=0; }; class _interface //   { private: char *text; double flo; int lo; _protocol *delegate;//     public: _interface(int Z, double f, char *u); _interface(int Z, double f, char *u, _protocol *_); void SetDelegate(_protocol *_); void action(); void viewResults(); ~_interface(); }; #endif 

')
For clarity, in _interface only the names of functions, their algorithms will be announced in a separate file, but for now it is worth discussing the code above. The _protocol structure is our list of delegate methods, it is husband to inherit from it, and then the interface delegating some actions (called _interface), people who know objective C have already noticed that the pointer to the delegate class has a certain type. The Complerator must establish a connection through the virtual functions table, and for this the pointer must have an object type with such a table.

The _interface class includes the following attributes: a pointer to a string, an integer number, a fractional number — enough to demonstrate how a delegate affects these private parameters. And now it’s worth showing what our interface does:

 #include "SomeInterfaceAndProtocol.hpp" #include "math.h" class realprotocol: public _protocol// ,      { int length(char *text) //     { int i=0; while(text[i])i++; return i; } void ActionString(char *stroka)//        { int len=this->length(stroka); int k=0; char Z; while(k!=(int)(len/2)) { Z=stroka[k]; stroka[k]=stroka[len-1-k]; stroka[len-1-k]=Z; k++; }; } int ActionRetNums(double S)//     { return (int)sqrt(S); } }; 


Pay attention (!): class realprotocol: public _protocol - you need to write like this, if you just declare a class as class realprotocol, and then write everything as well - it will not work, moreover, without a depraved typewriter, the compiler will not even collect it, objective C in this regard more compliant (see above), but here I am my flaws (and many).

And now is the time to show a listing where the delegating delegate and the delegates interact:

 #include <cstdlib> #include "SomeInterfaceAndProtocol.hpp" #include "realprotocol.hpp" realprotocol delegat; _interface delegator=_interface(44, 66.888, "seidal eht rof maj"); int main(int argc, char *argv[]) { delegator.SetDelegate(&delegat); delegator.action(); delegator.viewResults(); system("PAUSE"); return EXIT_SUCCESS; } 


Console with rezeltatami:

image

That's all by code - the string is expanded backwards before, the integer attribute is changed partly according to the rules of the object of the delegator, partly at the discretion of the object of the deligate, quite well demonstrates the essence of the delegation.

It is clear that this approach is not perfect, but C ++ does not predispose to delegation at all, without crutches, the object to which it is delegated may need to have inheritance from the other object and add a protocol to inheritance may not always work (the prohibition on the use of multiple inheritance in the project, virtual functions in other grades parents). Although why do we need a head? That's right - to come up with solutions, if there is no way with inheritance - the C ++ standard completely allows you to write this:

 class externalclass:someclass1, someclass2 { private: class internalclass:public _protocol { //-- }; internalclass forDelegate; public: _protocol* GetForDelegate() { return &forDelegate; } }; 


The outer and inner class can be so tightly linked that their interaction will give all that we need.

SUMMARY:

1) It is necessary to create for the class to be delegated, a class-protocol with virtual delegate functions and work with the object delegated through the pointer.
2) The delegated class must be inherited from the protocol.

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


All Articles