References and pointers of C ++ base classes and derived classes

Source: Internet
Author: User

Class {......} class B: Public {.....} (1) A * pA = new B (2) B; A & RB = B; (1) is a base class pointer pointing to a derived class instance? What is the significance of doing so? What does (2) mean? What is the purpose and meaning? Please provide more details. Thank you!

Question added:

Is the access range of Rb in (2) the same as that of B? Is there a difference? In my own experiment, PA can only call virtual functions of class B and public functions of Class A (the protection type is not tested, and it can be estimated ). It seems that the access range should be the intersection of Class A and Class B. The access range of Rb is similar to that of PA. Unlike B, Rb cannot access B's public functions. "The access range of pointer Pa and reference Rb is completely determined by the range defined by PA and Rb, and has nothing to do with the target they direct ." This is a reminder to me, but this sentence is also a bit problematic. It is still somewhat related to the target. The virtual function shows polymorphism, which is expressed by the target.

 

A base class pointer or reference to an instance of a derived class, which is widely used in object-oriented programming. A * pA = new B; this is a base class pointer pointing to an instance of a derived class. B; A & RB = B; this is a base class reference pointing to (reference) the instance of the derived class. The access range of the pointer Pa and reference Rb is completely determined by the range defined by PA and Rb, and is irrelevant to the target they direct. The significance of using a base class pointer or reference to access a derived class instance is that such pointers and references can be used to access the objects of all derived classes under this base class, in this aspect, we can use the object-oriented "polymorphism" feature. When we call virtual functions through this base class pointer or reference, we actually execute the functions of the derived class objects, the code of the pointer or referenced party does not need to change with the different Derived classes, but can achieve the purpose of executing the function (that is, the member function of the derived class) that best suits the derived class; on the other hand, it can make the program module have a good alternative, and replace another derived class with one derived class. The other part of the program can run normally without any changes and take advantage of the features of the new derived class. PS: base class pointers and references can be used to access the object of a derived class. These are base class objects. The theoretical basis is that a derived class object must be a base class object.

 

 

 

1. initialization sequence of Class Members
The title of clause 13 is: the members initialization order in the initialization list should be the same as the declared order in the class.
I don't know if you have paid attention to this issue when using C ++ for development. I never thought about it!
The following is an example:

Class cmyintarray
{
Public:
Cmyintarray (INT lowbound, int highbound );
Size_t getarraysize () const {return data. Size ();};
PRIVATE:
STD: vector <int> data;
Size_t size;
Int lbound, hbound;
};

Cmyintarray: cmyintarray (INT lowbound, int highbound)
: Size (highbound-lowbound + 1)
, Lbound (lowbound)
, Hbound (highbound)
, Data (size)
{
}

If I have not read this book and have no tips, I think many people who are engaged in C ++ development will not be able to see any problems with these simple lines of code (of course, compilation is certainly not a problem ).
However, if the program contains code similar to the following, the problem will pop up when the program is running:

Cmyintarray otest (5, 13 );
Cout <otest. getarraysize () <Endl;

And even if you are tracking in the debug status, it is difficult to find the root cause of the problem!
Where is the problem? In the Declaration Order of member variables! The preceding variable Declaration Order is changed:

Size_t size;
Int lbound, hbound;
STD: vector <int> data;

The problem can be solved!
Surprised? Why? The book provides the answer: the class members system is initialized in the order they are declared in the class; it has nothing to do with the order they appear in the member initialization list.
The root cause of the above Code error is that size is not defined during data initialization! That is to say, to initialize a vector with no defined size, an error will certainly occur.

2. Question about cutting"
The following is a passage in the book (in Clause 22 ):
When a derived class object is handed over as a base class object, all the features that are originally "becoming a derived class Object" will be removed (slicing, only one internal base class object is left.
Below is a small example I wrote:

Class cbase
{
Public:
Virtual void test () const {cout <"output from cbase! "<Endl ;};
};

Class cderived: Public cbase
{
Public:
Virtual void test () const {cout <"output from cderived! "<Endl ;};
};

The following are two functions:

Void test1 (cbase test)
{
Test. Test ();
}

Void Test2 (const cbase & test)
{
Test. Test ();
}

Use the following code to call test1 and Test2 respectively:

Cderived otest;
Test1 (otest );
Test2 (otest );

Question: What are output by calling test1 and Test2 respectively?
The correct answer is:

Output from cbase!
Output from cderived!

Surprised? Not surprising! The book has shown why this is the case: Passing parameters by reference has another advantage: Avoiding the so-called "slicing" problem ".

3. Static binding of non-virtual functions and dynamic binding of virtual functions
The following is an example:

Class cbase
{
Public:
Virtual void test () const {cout <"output from cbase! "<Endl ;};
};

Class cderived: Public cbase
{
Public:
Void test () const {cout <"output from cderived! "<Endl ;};
};

The following code is available:

Cderived D;

Cbase * pb = & D;
Pb-> test ();

Cderived * Pd = & D;
Pd-> test ();

The output is:

Output from cderived!
Output from cderived!

Everyone should know why. However, if you remove the virtual before the test method of cbase, the result will change! The output is:

Output from cbase!
Output from cderived!

At this time, some people will be surprised, Pb and PD point to D, why is it output like this?
The answer is: Non-virtual functions are statically bound, and virtual functions are dynamically bound.
Article 37 In the book provides advice: Never redefine the inherited non-virtual functions.

4. Static binding of default values
Let's look at the example:

Class cbase
{
Public:
Virtual void test (INT itest = 0) const = 0;
};

Class cderived: Public cbase
{
Public:
Void test (INT itest = 1) const {cout <itest <Endl ;};
};

The following is the call code:

Cbase * P = new cderived;
P-> test ();

Our intention is to output 1, but the result is 0!
Don't be surprised. The book provides the answer: the virtual function system is dynamically bound (dynamically bound), while the default parameter value is static binding (statically bound ).
Furthermore, article 38 in the book also gives you advice: Never redefine the inherited default parameters.

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.