C + + Experiment 2 -- Inheritance and polymorphism

1, Inheritance access test

Source code:

#include <iostream>
using namespace std;

class A_animal{
	public:
		void eat(){
			cout << "need eat" << endl;
		}
	protected:
		void sleep(){
			cout << "need sleep" << endl;
		}
	private:
		void stand(){
			cout << "can stand up" << endl;
		}
};

//Here is subclass B_dog can inherit parent class a through public inheritance, protected inheritance and private inheritance_ animal
class pub_B_dog : public A_animal{
	public:
		void pub_test(){
			eat();//Can access
			sleep();//The protected object in the base class can only be accessed by using the derived class object in the derived class
			//stand();// Cannot access
		}
		void pub_bark(){
			cout << "wangwang(pub)" << endl;
		}
	protected:
		void pub_tail(){
			cout << "short tail(pub)" << endl;
		}
	private:
		void pub_hair(){
			cout << "yellow(pub)" << endl;
		}
};
class pro_B_dog : protected A_animal{
	public:
		void pro_test(){
			eat();//Can access
			sleep();//The protected object in the base class can only be accessed by using the derived class object in the derived class
			//stand();// Cannot access
		}
		void pro_bark(){
			cout << "wangwang(pro)" << endl;
		}
	protected:
		void pro_tail(){
			cout << "short tail(pro)" << endl;
		}
	private:
		void pro_hair(){
			cout << "yellow(pro)" << endl;
		}
};
class pri_B_dog : private A_animal{
	public:
		void pri_test(){
			eat();//Can access
			sleep();//The protected object in the base class can only be accessed by using the derived class object in the derived class
			//stand();// Cannot access
		}
		void pri_bark(){
			cout << "wangwang(pri)" << endl;
		}
	protected:
		void pri_tail(){
			cout << "short tail(pri)" << endl;
		}
	private:
		void pri_hair(){
			cout << "yellow(pri)" << endl;
		}
};
int main()
{
	pub_B_dog A;

	A.pub_bark();//Derived classes can access public members in the base class
	A.eat();
	//A.sleep();// A derived class cannot access a protected member in a base class
	//A.stand();// Derived classes cannot access private members in a base class
	//A.pub_tail();
	//A.pub_hair();
	
	pro_B_dog B;
	B.pro_bark();
	//B.eat();
	//B.sleep();
	//B.stand();
	//B.pro_tail();
	//B.pro_hair();
	
	pri_B_dog C;
	C.pri_bark();
	//C.eat();
	//C.sleep();
	//C.stand();
	//C.pri_tail();
	//C.pri_hair();
	return 0;
}

1.public, protected and private inherited derived classes can access public and protected members in the base class;

2. The private member in the base class cannot be accessed directly in the derived class;

3. Derived class objects have access / modifiable permissions for public members in the base class only when they are derived from public. Others are inaccessible / modifiable.

4. The inheritance method will change the access rights of members inherited from the base class in the derived class:

      (1) . public inheritance does not change the access rights of base class members

      (2) . protected inheritance changes the public member in the base class into a protected member of a subclass, and the access permissions of other members remain unchanged

      (3) . private inheritance makes the access rights of all members of the base class in subclasses private

5.B inherits A in A private way, and uses {using A::_a;} to promote some public members in A to public

6. If you want these inherited data members to be public or protected members, you can redeclare them with using. The access permission of the name in the using declaration statement is determined by the access specifier before the using declaration statement.

2, Friend class inheritance test

Source code:

#include<istream>
using namespace std;
class A {
private:
	int a;
	friend class C;//Friend class C; 
};
class B: public A {
private:
	int b;
};
class C {
public:
	void Test() {
		B b1;
		b1.a;
		//b1._b; Inaccessible;
	}
};
class D :public C {
public:
	void Test() {
		A a1;
		//a1.a;// Inaccessible; 
		B b2;
		//b2.a;// Inaccessible; 
		//b2.b;// Inaccessible; 
	}
};

1. Friend relationship cannot be inherited. Friends of the base class do not have special access to members of the derived class.

2. If the base class is granted a friend relationship, only the base class has special access rights, and the derived class of the base class cannot access the class granted a friend relationship. When class y is described as a friend of class X, all member functions of Class Y become friend functions of class X, which means that as a friend, all member functions in class y can access all members (including private members) in class X.

3. Friend relationship is unidirectional and not exchangeable. Friend relationships are not transitive. Friend relationships cannot be inherited. The friend class of a base class may not be the friend of a subclass, and the subclass of a type of friend may not be the friend of that type.

3, Comprehensive application of polymorphism

1. General polymorphism:

Create a new CAnimal class. Move() is its internal virtual function. Create CCat class, CEagle class and COwl class to inherit the CAnimal class, and rewrite the implementation method of its internal virtual function move() to achieve the effect of polymorphism.

#include <iostream>
using namespace std;

class CAnimal
{
public:
    //non-parameter constructor 
    CAnimal() {
        m_nLegs = 2;
    }
    CAnimal(int nLeg) {
        m_nLegs = nLeg;
    }
    //virtual function
    virtual void Move() {
        cout << "I can crawl or fly!" << endl;
    }
protected:
    int m_nLegs;
};
class CCat : virtual  public CAnimal
{
public:
    //non-parameter constructor 
    CCat() {
        m_nLegs = 4;
    }
    CCat(int nLegs) {
        m_nLegs = nLegs;
    }
    virtual void Move() {
        cout << "I am a cat,I can crawl!" << endl;
    }
};
class CEagle : virtual public CAnimal
{
public:
    //non-parameter constructor 
    CEagle() {
        m_nLegs = 2;
    }
    CEagle(int nLegs) {
        m_nLegs = nLegs;
    }
    virtual void Move() {
        cout << "I am an eagle,I can fly!" << endl;
    }
};
class COwl : public CCat, public CEagle
{
public:
    //non-parameter constructor 
    COwl() {
        m_nLegs = 2;
    }
    COwl(int nLegs) {
        m_nLegs = nLegs;
    }
    virtual void Move() {
        cout << "I am an owl,I can also fly!" << endl;
    }
};

void TestAnimal()
{
    CAnimal* pAnimal[4];
    pAnimal[0] = new  CAnimal(2);
    pAnimal[1] = new CCat(4);
    pAnimal[2] = new CEagle(2);
    pAnimal[3] = new COwl(2);
    for (int i = 0; i < 4; i++)
    {
        pAnimal[i]->Move();
    }
}

int main() {
    TestAnimal();
    return 0;
}

  2. Special polymorphism

Input or output parameters are pointers to parent classes or references to base classes in subclasses, and pointers to subclasses or references to subclasses in subclasses

The special polymorphism here means that the parameter of the function is the pointer (Reference) of the parent class or the pointer (Reference) of the child class (that is, the binding of the virtual function is implemented during operation (runtime polymorphism)).

#include <iostream>
using namespace std;

class CAnimal
{
public:
    //non-parameter constructor 
    CAnimal() {
        m_nLegs = 2;
    }
    CAnimal(int nLeg) {
        m_nLegs = nLeg;
    }
    //virtual function
    virtual void Move() {
        cout << "I can crawl or fly!" << endl;
    }
protected:
    int m_nLegs;
};
class CCat : virtual  public CAnimal
{
public:
    //non-parameter constructor 
    CCat() {
        m_nLegs = 4;
    }
    CCat(int nLegs) {
        m_nLegs = nLegs;
    }
    virtual void Move() {
        cout << "I am a cat,I can crawl!" << endl;
    }
};
class CEagle : virtual public CAnimal
{
public:
    //non-parameter constructor 
    CEagle() {
        m_nLegs = 2;
    }
    CEagle(int nLegs) {
        m_nLegs = nLegs;
    }
    virtual void Move() {
        cout << "I am an eagle,I can fly!" << endl;
    }
};
class COwl : public CCat, public CEagle
{
public:
    //non-parameter constructor 
    COwl() {
        m_nLegs = 2;
    }
    COwl(int nLegs) {
        m_nLegs = nLegs;
    }
    virtual void Move() {
        cout << "I am an owl,I can also fly!" << endl;
    }
};

void callMove(CAnimal* pAn) {
    pAn->Move();
}

void TestAnimal()
{
    CAnimal animal;
    CEagle eagle;
    COwl owl;
    CCat cat;
    callMove(&animal);
    callMove(&eagle);
    callMove(&owl);
    callMove(&cat);
}

int main() {
    TestAnimal();
    return 0;
}

  3. Conformational polymorphism

When C + + polymorphism is applied, when the pointer to the base class is released, the destructor of the derived class is not called, resulting in the space applied in the derived class is not released, resulting in memory leakage.

#include <iostream>
using namespace std;
 
class Base {
public:
    Base() {cout << "Base constructor... \n";}
    ~Base() {cout << "Base destructor... \n";}
    virtual void fun() const {cout << "Base functoin...\n";}
};
 
class Derived :public Base {
public:
    Derived() {
        p = new int(0);
        cout << "Derived Constructor...\n";
    }
    ~Derived() {
        cout << "Derived destructor...\n";
        delete p;
    }
    void fun() const {cout << "Derived function...\n";}
private:
    int *p;
};
 
int main() {
    Base* pd = new Derived;
    pd->fun();
    delete pd;
    return 0;
}

Operation results:

 

The above running results show that the destructor of the derived class is not called, and the space applied by the constructor of the derived class is leaked, so the code can be changed to the following code:

class Base {
public:
    Base() {cout << "Base constructor... \n";}
    virtual ~Base() {cout << "Mammal destructor... \n";}
    virtual void fun() const {cout << "Base functoin...\n";}
};

  Operation results:

  By declaring the destructor of the base class as a virtual destructor, the destructor of the derived class is successfully called through the base class pointer, and the memory is released.

4. Multiple inheritance

Multi inheritance concept: if a derived class inherits from multiple base classes, it becomes multi inheritance.

Declaration of multiple inheritance:

Class derived class name: access control base class name 1, access control base class name 2{

        Member list

}

The following points should be noted:

1. The execution order of constructors of derived classes of multiple base classes is similar to that of single inheritance. The execution order depends on the order of inheriting the base class specified when defining the derived class.
2. A derived class object has multiple members of the base class. There will be no ambiguity when accessing members with different names; if different base classes have members with the same name, the derived class object should be identified when accessing.
3. If a derived class declares a new member with the same name as the base class member, the derived new member will overwrite the member with the same name of the base class. Using the member name directly can only access the members of the derived class.

class A
{
public:
    int a;
};
class B : public A
{
public:
    int b;
};
class C : public A
{
public:
    int c;
};
class D :public B, public C
{
public:
    int d;

    void fun() 
    {
        d = a;
    }
};

Keywords: C++

Added by jug on Wed, 10 Nov 2021 22:36:49 +0200