Class base1
{
Public:
Base1 () {abc = 1 ;}
~ Base1 (){}
Void testfunc () {printf ("this is base1's func ~! /N ");}
Int ABC;
};
Class base2
{
Public:
Base2 () {abc = 2 ;}
~ Base2 (){}
Void testfunc () {printf ("this is base2's func ~! /N ");}
Int ABC;
};
Class son: Public base1, public base2
{
Public:
Son (){}
~ Son (){}
Void showabc () {printf ("ABC: % d/N", base1: ABC );}
};
Int main ()
{
Son testit;
Testit. showabc ();
Testit. base2: testfunc ();
Return 1;
}
As you can see, because the member functions and member variables of the two base classes have the same names, we must specify the member of the base class when referencing, otherwise, a prompt similar to the following will appear during compilation:
Compiling...
Main. cpp
F:/new study material/vc6test/main. cpp (76): error C2385: 'son: testfunc' is ambiguous
F:/new study material/vc6test/main. cpp (76): warning C4385: cocould be the 'testfunc' in base'base1' of class 'son'
F:/new study material/vc6test/main. cpp (76): warning C4385: or the 'testfunc' in base 'base2' of class 'son'
This indicates that the compiler does not know which testFunc you want to use ......
Reprinted as follows:
C ++ allows derivative classes to directly bear more than two parent classes at the same time, for example, A and B, you can use the following method to allow C to directly inherit the two types:
Class C: public A, public B {
Public:
C (int x): A (x), B (x) {// create A letter call under multiple slave nodes
// Implement
}
// Implement
};
The above also shows the construction mechanism call after the contract, there is no such method for writing the interface, it is automatically called, and the structure function is also automatically called.
After multi-factor inheritance, the constructor's row sequence is determined from left to right based on the sequence of the program you created. The last step is to derive the class difference after the program is written, for example, in the above example, the constructor of type A is first written, and then the constructor of type B is written, the last line is the constructor function of class C, while the reverse line of the constructor function is the opposite. The first line is used to derive the constructor function of class C, then, right-click the row on the left and use the following example to show the result:
# Include <iostream>
Using namespace std;
Class FooA {
Public:
FooA (){
Cout <"construct row FooA constructor" <endl;
}
~ FooA (){
Cout <"Statement row FooA decoding mechanism" <endl;
}
};
Class FooB {
Public:
FooB (){
Cout <"Statement row FooB constructor" <endl;
}
~ FooB (){
Cout <"Statement row FooB decoding mechanism" <endl;
}
};
Class FooC: public FooA, public FooB {
Public:
FooC (){
Cout <"Statement row FooC constructor" <endl;
}
~ Fooc (){
Cout <"Statement row fooc decoding mechanism" <Endl;
}
};
Int main (){
Fooc C;
Cout <Endl;
Return 0;
}
The result of the rows:
Authorization row fooa Constructor Authorization row foob Constructor Authorization row fooc ConstructorReturns the fooc structure of the row. Returns the foob structure of the rows. Returns the fooa structure of the rows.
|
In multiple stages, one of the base classes is usually not private, while the others are used to present a complete abstract interface.
You have a method dorequest (). You cannot know in advance what type of objects will be imported, or this method can accept any type of objects, if you want to operate a specific method on an object, such as the dosomething () method, the problem is that the imported object is arbitrary, unless you define an abstract object and declare a dosomething () abstract method, and then let all the other classes inherit this abstract object, otherwise, your dorequest () method does not seem to be implemented, and there is no limit for such operations.
You can solve this problem with multiple factors, such as first defining an abstract class:
#ifndef IREQUEST
#define IREQUEST
class IRequest {
public:
virtual void execute() = 0;
};
#endif
Assume that you have the following types of SomeObject:
#ifndef SOMEOBJECT
#define SOMEOBJECT
#include <iostream>
using namespace std;
class SomeObject {
public:
virtual void someFunction() {
cout << "do something" << endl;
}
private:
void otherFunction() {
cout << "do other" << endl;
}
};
#endif
In order to meet the previously provided doRequest () requirements, you must allow derivative classes to inherit IRequest and SomeObject classes at the same time, such:
#include "IRequest.h"
#include "SomeObject.h"
#include <iostream>
using namespace std;
class Welcome : public SomeObject, public IRequest {
public:
void execute() {
cout << "Welcome!!" << endl;
}
};
#include "IRequest.h"
#include "SomeObject.h"
#include <iostream>
using namespace std;
class Hello : public SomeObject, public IRequest {
public:
void execute() {
cout << "Hello!!" << endl;
}
};
Assume that you have designed a doRequest () method. Although you do not know what type of requests Hello and Welcome are, they all accept IRequest, so doRequest () as long as you know what public interfaces are defined by IRequest, you can operate the Hello and Welcome instances without knowing what kind of instances the imported objects are, use the following program to compile the program:
#include <iostream>
#include "IRequest.h"
#include "Welcome.h"
#include "Hello.h"
using namespace std;
void doRequest(IRequest *request) {
request->execute();
}
int main() {
Welcome welcome;
Hello hello;
doRequest(&welcome);
doRequest(&hello);
return 0;
}
The result of the rows:
In the past, we have always been engaged in the inheritance of a single class, but in real life, some new things often have the attributes of two or more things. To solve this problem, c ++ introduces the concept of multi-inheritance,C ++ allows you to specify multiple base classes for a derived class. This inheritance structure is called multi-inheritance..
For example, a vehicle and a ship can be derived from a subclass. However, a vehicle and a ship share the same characteristics as an amphibious vehicle and must inherit the common attributes of a vehicle and a ship.
It is not difficult to come up with the following legends and code:
To use multiple inheritance for a derived class, you must list the class names of all the base classes after the derived class name and colon, and use them to separate them.
// Program Author: Guan Ning
// Site: www.cndev-lab.com
// All the manuscripts are copyrighted. If you want to reprint them, be sure to use the famous source and author.
# Include <iostream>
Using namespace STD;
Class Vehicle
{
Public:
Vehicle (INT Weight = 0)
{
Vehicle: Weight = weight;
}
Void setweight (INT weight)
{
Cout <"Reset weight" <Endl;
Vehicle: Weight = weight;
}
Virtual void showme () = 0;
Protected:
Int weight;
};
Class car: public vehicle // car
{
Public:
Car (INT Weight = 0, int AIRD = 0): Vehicle (weight)
{
Car: aird = aird;
}
Void ShowMe ()
{
Cout <"I'm a car! "<Endl;
}
Protected:
Int aird;
};
Class Boat: public Vehicle // Boat
{
Public:
Boat (int weight = 0, float tonnage = 0): Vehicle (weight)
{
Boat: tonnage = tonnage;
}
Void ShowMe ()
{
Cout <"I'm a ship! "<Endl;
}
Protected:
Float tonnage;
};
Class amphibiancar: Public car, public boat // dual-purpose vehicle, multiple inheritance embodiment
{
Public:
Amphibiancar (INT weight, int AIRD, float tonnage)
: Vehicle (weight), car (weight, AIRD), boat (weight, tonnage)
// Pay attention to calling the base class constructor for multiple inheritance
{
}
Void showme ()
{
Cout <"I'm a dual-purpose vehicle! "<Endl;
}
};
Int main ()
{
AmphibianCar a (4,200, 1.35f); // Error
A. SetWeight (3); // Error
System ("pause ");
}
On the surface, the above Code does not show obvious syntax errors, but it cannot be compiled. Why?
This is caused by the ambiguity of inheritance caused by multiple inheritance.
First look at the figure below:
In the figure, the primary problem lies in the deep red mark. The amphibious vehicle class inherits the attributes and methods from the Car class and the Boat class, and the Car class and the Boat class are the same as the base class of the AmphibianCar class, on the memory allocation, AmphibianCar obtains the SetWeight () member function from two classes. When we call. when SetWeight (3) is used, the computer does not know how to select the repeated class member function SetWeight () that belongs to two base classes ().
Because of this fuzzy problem, AmphibianCar a (4,200, 1.35f) is also caused. If the execution fails, the system will generate a Vehicle "not a base or member error.
The above code is used as an example. To make the AmphibianCar class get a copy of Vehicle, in addition, data members and member functions of the Car and Boat classes must be shared throughVirtual inheritanceTechnology.
We inherit the Vehicle class from the Car class and Boat class, and add the virtual keyword before it to implement virtual inheritance. After using virtual inheritance, when the system encounters multiple inheritance, it will automatically add a copy of Vehicle. When a copy of Vehicle is requested again, it will be ignored to ensure the uniqueness of the inherited class member functions.
The modified code is as follows. Observe the changes:
// Program Author: Guan Ning
// Site: www.cndev-lab.com
// All the manuscripts are copyrighted. If you want to reprint them, be sure to use the famous source and author.
# Include <iostream>
Using namespace std;
Class Vehicle
{
Public:
Vehicle (int weight = 0)
{
Vehicle: weight = weight;
Cout <"loading Vehicle class constructor" <endl;
}
Void SetWeight (int weight)
{
Cout <"Reset weight" <endl;
Vehicle: weight = weight;
}
Virtual void ShowMe () = 0;
Protected:
Int weight;
};
Class Car: virtual public Vehicle // Car, where virtual inheritance
{
Public:
Car (int weight = 0, int aird = 0): Vehicle (weight)
{
Car: aird = aird;
Cout <"loading Car class constructor" <endl;
}
Void ShowMe ()
{
Cout <"I'm a car! "<Endl;
}
Protected:
Int aird;
};
Class Boat: virtual public Vehicle // ship, where virtual inheritance
{
Public:
Boat (int weight = 0, float tonnage = 0): Vehicle (weight)
{
Boat: Tonnage = tonnage;
Cout <"load boat class constructor" <Endl;
}
Void showme ()
{
Cout <"I'm a ship! "<Endl;
}
Protected:
Float tonnage;
};
Class amphibiancar: Public car, public boat // dual-purpose vehicle, multiple inheritance embodiment
{
Public:
AmphibianCar (int weight, int aird, float tonnage)
: Vehicle (weight), Car (weight, aird), Boat (weight, tonnage)
// Pay attention to calling the base class constructor for multiple inheritance
{
Cout <"loading AmphibianCar class constructor" <endl;
}
Void ShowMe ()
{
Cout <"I'm a dual-purpose vehicle! "<Endl;
}
Void ShowMembers ()
{
Cout <"weight:" <weight <"pause," <"Air Displacement:" <aird <"CC," <"displacement: "<tonnage <" Don "<endl;
}
};
Int main ()
{
AmphibianCar a (4,200, 1.35f );
A. ShowMe ();
A. ShowMembers ();
A. SetWeight (3 );
A. ShowMembers ();
System ("pause ");
}
Observe the construction sequence of the class constructor.
Although Virtual inheritance is similar to virtual functions, readers must remember that there is absolutely no connection between them!