Objective C ++ clause 37: Never redefine the inherited default parameter value

Source: Internet
Author: User

Key points:

  • Do not redefine an inherited default parameter, because the default parameters are static binding, and virtualFunction-the only thing you should override-is dynamic binding..

 

 

Virtual functions are dynamically bound, but the default parameter is static binding. The so-called static type of an object is the type it uses when declared in a program.

Class Shape {public: enum ShapeColor {Red, Green, Blue}; virtual void draw (ShapeColor = Red) const = 0 ;}; class Rectangle: public Shape {public: // assign different default parameters. This is really bad! Virtual void draw (ShapeColor color = Green) const;}; class Circle: public Shape {public: virtual void draw (ShapeColor color) const; // when the customer calls this function as an object, you must specify the parameter value // because the function under static binding does not inherit the default parameter value from its base // but if you call this function using a pointer (or reference, you do not need to specify the parameter value // This function will inherit the default parameter value from its base under dynamic binding };

 

Shape * ps; // The static type is Shape * pc = new Circle; // The static type is Shape * pr = new Rectangle; // The static type is Shape *

Ps, pc, and pr no matter what these pointers point to, their static types are Shape * objects. The so-called dynamic types refer to "types of objects currently referred ". Can be changed during Program Execution

ps = pr;ps = pc;

 

Virtual functions are dynamically bound. This means that when a virtual function is called, which function implementation code is called depends on the dynamic type of the called object:

Pc-> draw (Shape: Red) // call Circle: drawpr-> draw (Shape: Red) // call Rectangle: draw

When considering virtual functions with default parameters, because virtual functions are dynamically bound, the default parameters are statically bound. This means that when you call a virtual function defined in derived class, you can use base class to specify the default parameter value:

Pr-> draw (); // call Rectangle: draw (Shape: Red )!

The dynamic type of pr is Rectangle *, so the virtual function of Rectangle is called. Rectangle: The default parameter of the draw function should be Green, but because the pr static type is Shape *, the default parameter value called comes from the Shape class rather than the Rectangle class!

Even if you replace the pointer with reference, the problem still exists.

Why does c ++ stick to this well-behaved approach? The answer is efficiency during the runtime. If the default parameter is dynamically bound, the compiler must have some way to determine the appropriate parameter default value for the virtual function at runtime. This is more slow and complex than the current mechanism of "determining during compilation. C ++ makes such a trade-off to make the execution speed of the program and the simplicity of the compiler implementation. The result is the execution efficiency you enjoy today.

 

What happens if you follow this rule and provide the default parameter value to the base and derived classes users?

class Shape { public:     enum {Red, Green, Blue};     virtual void draw(ShapeColor color = Red) const = 0; };class Rectangle : public Shape { public:     virtual void draw(ShapeColor color = Red) const; };

Code already exists. Worse, there is dependency. If the default parameter value in the Shape changes, all the derived classes that "repeat the default parameter value" must also change, otherwise, they will eventually lead to "repeatedly defining an inherited default parameter value ".

What should I do?

When you want to make virtual functions show the behavior you want, you have to worry about replacing the design. Clause 35. One of them is the NVI method:

Make a public non-virtual function in the base class call a private virtual function, which can be redefined by derived classes. Here we can let the non-virtual function specify the default parameter, while the private virtual function is responsible for the real work:

Class Shape {public: enum {Red, Green, Blue}; void draw (ShapeColor color = Red) const {doDraw (color);} private: virtual void doDraw (ShapeColor color) const = 0 ;}; class Rectangle: public Shape {public: private: virtual void doDraw (ShapeColor) const; // you do not need to specify the default parameter };

Since the non-virtual function should never be overwritten by derived classes (Clause 36), this design clearly makes the default color parameter value of the draw function always Red.

Related Article

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.