What is the use of member functions in C ++?

For a class with a member template function like this:

template <typename t> class complex { public: complex(tr, t im); template<typename u> complex(const complex<u>&); private: //what would be the type of real and imaginary data members here. } 

I am confused about the functions of member templates, please indicate an example by which I understand the need for member template functions.
Also, tell me the use of member template functions in C ++, what are the situations when we use member template functions?

+4
source share
6 answers

The general purpose and functionality of the member function templates is no different from ordinary function templates (non-members). The only [insignificant] difference is that member functions have access to the implicit this parameter.

You understand the general purpose of regular function templates, right? Well, in that case you should understand the general purpose of member function templates, because it is exactly the same.

+3
source

This gives you the ability to do conversions:

 complex<int> ci; complex<float> cf(ci); 

So, if you have two types T1 and T2, and you can assign T1 to T2, this will allow you to assign complex<T1> a complex<T2> .

As for the question in your code (what will be the type of real and imaginary data elements here):

 template <typename t> class complex { ... private: t real_part; t imaginary_part; }; 
+5
source

The most common valuable use of the member functions that I encounter in everyday life is to reduce code complexity by providing one template function instead of many functions that do pretty much the same thing.

For example, suppose you are working on a server that receives half a dozen related messages and stores incoming data in half a dozen tables in a database. The direct implementation will be the implementation of 6 message processing functions (psudocode):

 class MessageProcessor { void OnMessage(const char* msg); void ProcessMessage100(Data100* data); void ProcessMessage101(Data101* data); void ProcessMessage102(Data102* data); void ProcessMessage103(Data103* data); void ProcessMessage104(Data104* data); void ProcessMessage105(Data105* data); }; MessageProcessor::OnMessage(const char* msg) { unsigned int * msgType = ((unsigned int*)msg); switch( *msgType ) { case 100 : ProcessMessage100((Data100*),sg); break; case 101 : ProcessMessage101((Data101*),sg); break; :: } } MessageProcessor::ProcessMessage100(Data100* data) { Record100* record = GetRecord100(key); record->SetValue(xyz); } MessageProcessor::ProcessMessage101(Data101* data) { Record101* record = GetRecord101(key); record->SetValue(xyz); } : : 

There is an opportunity to generalize ProcessMessage () functions, since they do essentially the same thing:

 class MessageProcessor { OnMessage(const char* msg); template<class Record, class Data> void Process(Data* data); }; template<class Record, class Data> void MessageProcessor::Process<Record,Data>(Data* data) { Record* record = GetRecord(key); record->SetValue(xyz); } 

The GetRecord function can also be generalized, which gives a code base with two functions, where it used to be 12. This improves the code due to its simplicity with fewer moving parts, it is easier to understand and maintain.

+4
source

Using the example you provided, the member template function allows you to build an instance of complex<T> from complex<U> .

As a concrete example of when this might be useful, suppose you have a complex<double> but a complex<float> is required. Types are not bound without a constructor, so a regular copy constructor will not work.

+1
source

Often you want a member function of your class to work in a range. Thanks to the presence of template member functions, you can work on ranges that are independent of the container that provides the range without providing a free feature.

The same goes for functors. Often you write a functor that runs on a specific pair of iterators, but soon realizes that the functor can function on any range. Therefore, instead of providing template parameters through an encapsulating structure, you can provide them through a member operator () and make a type inference possible.

0
source

The first examples that come to mind:

  • In some container constructors (or assign methods) to input input iterators of an unknown type.

  • std::complex to allow working with different types than the one from which the std::complex instance was created.

  • In shared_ptr (be it std::tr1:: or boost:: so that you can store different types of pointers in an instance of a shared object on the heap (for which pointer types can be obtained).

  • In thread (be it std:: in C ++ 0x or boost:: to get a functor of an unknown type that will be called by the thread instance.

In all cases, the use is the same: you have a function that works with unknown types. Since AndreyT perfectly asserts the same thing as with regular functions.

0
source

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


All Articles