Transfer from reference to design mode (lower) and design mode

Source: Internet
Author: User

Transfer from reference to design mode (lower) and design mode

At the end of the previous article, from the introduction to the design model (I ),Non-Virtual InterfaceThe implementation of NVI, that is, virtual functions are declared as protected or private, implemented by using the template function mode.

Yuanyou @ KillU looked very carefully and raised a question: can virtual functions be inherited if they are of the private type? The answer is: yes.

5. Implement and call Permissions

<Negative tive C ++> explains how to rewrite a virtual function to call a virtual function, when to do things (when)

In the NVI or template function mode, you can allow the derived class to override the virtual function and grant the derived class the "Implementation right"-that is, the implementation of the function; however, the base class still has the "Call permission"-that is, when to call a virtual function

It sounds like an example. Let's look at an instance or the implementation of the template function mode. It's just that the virtual function is declared as private)

5.1 Private virtual functions

The base class AbstractClass and the derived class ConcreteClass

class AbstractClass {public:    void TemplateMethod();private:    virtual void PrimitiveOperation1();    virtual void PrimitiveOperation2();};class ConcreteClass : public AbstractClass {private:    void PrimitiveOperation1() override;    void PrimitiveOperation2() override;};

Two virtual functions PrimitiveOperation1, PrimitiveOperation2, and TemplateMethod in the basic AbstractClass

// implementation of private member functionvoid AbstractClass::PrimitiveOperation1() { std::cout << "Operation1 from AbstractClass !" << std::endl; }void AbstractClass::PrimitiveOperation2() { std::cout << "Operation2 from AbstractClass !" << std::endl; }// implementation of non-virtual member functionvoid AbstractClass::TemplateMethod() 
{ PrimitiveOperation1(); PrimitiveOperation2();}

In the ConcreteClass of the derived class, rewrite two virtual functions: PrimitiveOperation1 and PrimitiveOperation2.

// overridevoid ConcreteClass::PrimitiveOperation1() { std::cout << "Operation1 from ConcreteClass !" << std::endl; }void ConcreteClass::PrimitiveOperation2() { std::cout << "Operation2 from ConcreteClass !" << std::endl; }

When a virtual function is called through a pointer or reference, whether it is a base class or a virtual function in a derived class depends on the dynamic binding to the pointer or referenced class object.

// call virtual functions in AbstractClassAbstractClass* p1 = new AbstractClass;p1->TemplateMethod();// call virtual functions in ConcretetClassAbstractClass* p2 = new ConcreteClass;p2->TemplateMethod();

The output result is as follows:

Operation1 from AbstractClass !Operation2 from AbstractClass !Operation1 from ConcreteClass !Operation2 from ConcreteClass !

At first glance, this result does not immediately raise questions, because the derived classes have rewritten two virtual functions, which are also the private member functions of the derived classes, it is no problem to call the virtual functions in your own class.

5.2 virtual functions are not overwritten

The following changes the program. The ConcreteClass class of the derived class does not overwrite two virtual functions, but simply inherits from the base class AbstractClass, as shown below:

class ConcreteClass : public AbstractClass { };

Execute the program and output the result:

Operation1 from AbstractClass !Operation2 from AbstractClass !Operation1 from AbstractClass !Operation2 from AbstractClass !

At this time, the question arises: how can a derived class ConcreteClass access the base class AbstractClass?Private virtual functions? This isPrivate type!

In fact, this is an illusion, not that the derived class directly calls the private virtual function of the base class,Non-virtual member functions of a derived classConcreteClass: TemplateMethod,

Because it is inherited fromNon-virtual member functions of the base classAbstractClass: TemplateMethod, which indirectly callsPrivate virtual functions.

The actual "Call permission" is still in the hands of the base class, but the base class provides a TempaltMethod interface, which can be called indirectly by the derived class.

5.3 private non-virtual functions

Modify the program again. PrimitiveOperation1 and PrimitiveOperation2 in the base class are no longer declared as virtual functions, that is, the base class revokes the "Implementation right" of the function from the derived class"

class AbstractClass {public:    void TemplateMethod();private:    void PrimitiveOperation1(); // non-virtual    void PrimitiveOperation2(); // non-virtual};

At the same time, in the derived class ConcreteClass, declare your own private member functions PrimitiveOperation1 and PrimitiveOperation1, and "hide" The functions of the same name in the base class

class ConcreteClass : public AbstractClass {private:    void PrimitiveOperation1();    void PrimitiveOperation2();};

Execution program output result:

Operation1 from AbstractClass !Operation2 from AbstractClass !Operation1 from AbstractClass !Operation2 from AbstractClass !

The output result is the same as that of 5.2. The derived class calls ConcreteClass: TemplateMethod, while ConcreteClass: TemplateMethod inherits from AbstractClass: TemplateMethod,

Therefore, in factNon-virtual member functions in the base class,CallPrivate member functions in the base class

5.4 pure virtual functions

Reiterate one sentence in section 5.1:When you call a virtual function through a pointer or reference, the actual call to the base class or the virtual function in the derived class depends on the private member function dynamically bound to the pointer or the referenced Class Object base class.

So understandable,Virtual FunctionsIt involvesDynamic binding does not have much to do with whether it is public, private, or protected.

In practice, since the template method mode is to be used, it means that PrimitiveOperation1 and PrimitiveOperation2 must be rewritten in the ConcreteClass of the derived class.

To ensure that these two functions will be overwritten by the derived classes, you can declare them as pure virtual functions, that is, add "= 0" at the end of the function, as shown below:

class AbstractClass {public:    void TemplateMethod();private:    virtual void PrimitiveOperation1() = 0;    virtual void PrimitiveOperation2() = 0;};

In this case, because the base class declares pure virtual functions, all base classes become oneAbstract base class)

Abstract base classes can only provide interfaces, whileCannot be instantiated,An error occurs when you execute the following code:

AbstractClass* p1 = new AbstractClass;  // error !p1->TemplateMethod();

 

Summary:

1) NVI gives the derived class control overHowFunctionality is implemented, but the base class reserves the rightWhenThe function will be called

2) Derived classes may redefinePrivateInherited virtual functions

3) Pure virtual functions specify inheritance of interface only

 

References:

<Valid tive C ++> item 35

<C ++ Primer_5th> 15.4 Abstract Base Classes

<Design Patterns> Template Method

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.