Transformations and inheritance, virtual functions
Understanding conversions between base and derived classes are essential to
Understanding how object-oriented Programming works in C + +.
Understanding the transformation between a base class and a derived class is an indispensable understanding of object-oriented programming.
Like built-in pointers, the smart pointer classes (§12.1, p.)
Derived-to-base Conversion-we can store a pointer to a derived object in a
Smart pointer to the base type.
Like a built-in pointer, the smart pointer class supports the transformation of the exported to base class to store a pointer to a derived class object
A pointer to the base class type.
Static type and dynamic type (statically and dynamically typed)
class Quote
{
public:
Quote () = default;
Quote (const string & book, double sales_price): bookNo (book), price (sales_price)
{cout << "Quote gouzhao function" << endl;}
string isbn () const {return bookNo;}
// Return the total sales price of the specified number of items
// Derived classes will be rewritten to apply different discount algorithms
virtual double net_price (size_t n) const {return n * price;}
virtual ~ Quote () = default; // Dynamic link destructor
private:
string bookNo; // isbn number of this book
protected:
double price = 0.0; // price without discount
};
// Inheritance, how to inherit?
class Bulk_quote: public Quote
{
public:
Bulk_quote () = default;
Bulk_quote (const string & book, double p, size_t qty, double disc)
: Quote (book, p), min_qty (qty), discount (disc)
{cout << "Bulk_quote construct function" << endl;}
// Override virtual function
double net_price (size_t n) const override {cout << "double net_price (size_t)" << endl; return n * price;}
// Again, please remember to define it after you declare the function. Otherwise I have made some inexplicable mistakes!
// ~ Bulk_quote2 () {cout << "~ Bulk_quote2 ()" << endl;}
private:
size_t min_qty = 0;
double discount = 0.0;
};
There is No implicit Conversion from Base to Derived ...
void fun1 ()
{
Quote base;
// Bulk_quote * bulkP = & base; error cannot convert base class to derived class
// Bulk_quote & bulkRef = base; same as above
Bulk_quote bulk;
Quote * itemP = & bulk; // Derived class is converted to base class
// Bulk_quote * bulkP = itemP; error: base class to derived class
}
... and No Conversion between Objects
void fun2 ()
{
Bulk_quote bulk; // Derived class
Quote item (bulk); // Call the base class Quote constructor
item = bulk; // calls Quote :: operator = (const Quote &)
}
This is when our reference object is the base class. Only the base class part is copied when the conversion occurs. And that part of the derivation
will be ignored directly
Virtual Functions Imaginary function
Key concept:conversions among Types related by inheritance
There is three things that is important to understand about conversions
Among classes related by inheritance:
? The conversion from derived to base applies only to pointer or reference
Types.
? There is no implicit conversion from the Base-class type to the derived
Type.
? Like any member, the Derived-to-base conversion could be inaccessible due
To access controls.
Key concepts: Conversions between types of inheritance relationships
The three most important things to convert in a class that are associated with inheritance:
? Conversions from a derived class to a base class apply only to pointers or reference types.
There is no implicit conversion from base class to derived class
? A conversion from a derived class to a base class, like no member, may be inaccessible because of access control.
Dynamic binding
double print_total (ostream & os, const Quote & item, size_t n)
{
// Bound to the type of this parameter according to different objects
// quote Quote :: net_price or Bulk_quote :: net_price here
double ret = item.net_price (n);
os << "ISBN:" << item.isbn () // Call Quote :: isbn
<< "# sold:" << n << "total due:" << ret << endl;
return ret; // The above Quote parameter can accept Quote or Bulk_quote type
}
Calls to Virtual Functions is resolved at Run time
The virtual function that is called can be determined at execution time
void fun3 ()
{
Quote base ("0-201-82470-1", 50);
print_total (cout, base, 10); // Call Quote's net_price
Bulk_quote derived ("0-201-82470-1", 50, 5, 0.19);
print_total (cout, derived, 10); // call net_price of Bulk_quote
base = derived; // copy the part of quote type to base
base.net_price (20);
}
Virtual Functions in a Derived class ("Virtual function in derived class")
A function, that is, virtual in A base class was implicitly virtual in its
Derived classes. When a derived class overrides a virtual, the parameters in
The base and derived classes must match exactly.
The final and override specifiers
(1) Several functions that are overloaded must be in the same class.
The overridden function must be in a different class that has an inheritance relationship
(2) Several functions that are covered must have the same function name, parameters, and return values;
Overloaded functions must have the same function name, with different parameters. The purpose of the different parameters is to use the parameter to infer which function the program is calling when the function is called.
It is also very natural to explain why a function cannot be overloaded by a different return value. Since the program is most likely not to care about the return value when calling a function, the compiler cannot see from the code which function the program is calling.
(3) Keywordvirtual must be added before the function is covered;
Overloading and virtual do not have anything to do with it, nor does it affect the operation of overloading.
struct B
{
virtual void f1 (int) const;
virtual void f2 ();
void f3 ();
};
struct D1: B // What is this inheritance?
{
void f1 (int) const override; // ok can override
// void f2 (int) override; error does not have the virtual function f2 (int)
// void f3 () override; // error: f3 () is not a virtual function
// void f4 () override; error: There is no virtual function f4 ()
};
Final this keyword
struct D2: B
{
// Inherit f2 from B, after f3 we override f1
void f1 (int) const final; // derived classes cannot override f1 afterwards
};
struct D3: D2
{
void f2 ();
// void f1 (int) const; // Note: This function is a function modified by final
};
virtual Functions and default Arguments (virtual functions and Defaults)
Virtual functions that have a default number of parameters should use the same parameters in the base value and the derived class.
Circumventing the Virtual mechanism
void fun4 ()
{
cout << "there is fun4" << endl;
Quote * baseP;
double undiscounted = baseP-> Quote :: net_price (42);
}
Ordinarily, only code inside member functions (or friends) should need
The scope operator to circumvent the virtual mechanism
Usually only member functions (friend functions) within a class need to use scope operators to circumvent virtual mechanisms
15.4. Abstract Base Classes
abstract classes are classes in which a pure virtual member function is defined
Why do you define abstract base classes? In my opinion, there are the following reasons:
1. The most important reason is the ability to separate the interface from the implementation.
Interface is the most valuable resource of a software product.
Designing an interface requires more expensive costs than implementing an interface.
Therefore, to protect the interface,
In order to avoid changes in response to customer needs, the program ape accidentally destroyed the interface.
2. The introduction of abstract base classes and pure virtual functions facilitates the implementation of C + + polymorphic characteristics.
The ability to invoke a method of a subclass object with a pointer to an abstract base class.
3. Very many times. It is unreasonable for many base classes to be instantiated.
such as the "shape" of the base class, after being instantiated will be quite confusing,
So simply define the "shape" class as an abstract class, derived from a square, a triangle, and other subclasses.
Pure virtual function
When a pure virtual function is included in a class declaration. You cannot create an object of this class.
The pure virtual function of the base class must have "= 0", but not necessarily the implementation of the function, simply cannot be embedded directly in the class.
class Disc_quote: public Quote
{
public:
Disc_quote () = default;
Disc_quote (const string & book, double price, size_t qty, double disc):
Quote (book, price), quantity (qty), discount (disc) {cout << "Disc_quote constructor" << endl;}
double net_price (size_t) const = 0; // Pure virtual function
protected:
size_t quantity = 0;
double discount = 0.0;
};
A pure virtual function cannot be defined directly inside a class. To define it, it's going out.
virtual void Move (int nx, int ny) = 0;
void Baseellipse::move (int nx, int ny) {x = NX; y = ny;}
This is agreed.
classes that contain pure virtual functions are abstract classes
void fun5 ()
{
cout << "there is fun5" << endl;
// Disc_quote discount; // error: Disc_quote is an abstract class that cannot be instantiated with pure virtual functions
Bulk_quote bulk; // ok, there is no pure virtual function in this, not an abstract class
}
A Derived class Constructor initializes its Direct Base class only
Is that the derived class table can initialize the base class directly
class Bulk_quote2: public Disc_quote
{
public:
Bulk_quote2 () = default;
// Direct initialization
Bulk_quote2 (const string & book, double price, size_t qty, double disc):
Disc_quote (book, price, qty, disc) {}
double net_price (size_t) const override; // override pure virtual function
};
Some people think that to be true, so speak straight. The result is to go straight to offend. In fact a blunder. Chinese people write "true" word, is "straight" the following two points. That is to say, some truth, blunt, also want to keep two points. Don't say anything. To be honest is true, but to tell the truth is stupid. A man who can't hide in his belly thinks he is telling the truth. In fact, it's just a lack of EQ.
Unfortunately, the author seems to be neither true nor straight ~~~~~
Copyright notice: This article blog original articles, blogs, without consent, may not be reproduced.
"Footstep C++primer" 52, converting and inheriting virtual functions