C++ Understanding Object-Oriented Part 2

C++ Deeply Understanding Object-Oriented Parts

1. Object Oriented Deep Part

_After 360 tries in the past few days, I felt that I would be still difficult. I chose them randomly before I had learned them. The results of running the part of the algorithm questions were also correct, but I have not seen any of the two answers at all, so I skipped them directly. Keep working hard.Recently, I have changed my resume again to prepare for an internship and continue to deliver the autumn enrollment.Continue to refresh the course and now start learning the important object-oriented features and usage methods.

1. Inheritance and Derivation

1.1 Inheritance and Derivation

Inheritance: When defining a new class B, if it is similar to an existing class A (meaning that B has all the features of A), then A can be used as a base class and B as a derived class (also called a subclass) of the base class.Derived classes are modified and expanded from base classes.In derived classes, new member variables and member functions can be expanded.Once defined, derived classes can be used without dependency on the base class.
Derived classes have all member functions of the base class, whether private, protected, public.Private members of base classes cannot be accessed in member functions of derived classes.Write as

class Derived Class Name:public Base Class Name{};

class Student{
	private:
		string Name;
		int age;
	public:
		bool IsThreeGood(){};
		void setName(const string & name);
		{Name = name;}
		// ...
};

class UndergraduateStudent:public Student{
	private:
		int Department;
	public:
		bool IsThreeGood(){......}; // cover
		bool CanBaoYan(){......};
};  // Derived class writing: class name puclic base class name

class GraduateStudent:public Student{
	private:
		int Department;
		char mentorName[20];
	public:
		int CountSalary(){};
};

_The volume of a derived class object is equal to the volume of a base class object, plus the volume of its own member variables.A derived class object contains a base class object, and the base class object is stored in a location that precedes the new member variables added to the derived class object.For example,

#include <iostream>
#include <string>
using namespace std;

class Student{
    private:
        string name;
        string id;
        char gender; // "F" for women and "M" for men
        int age;
    public:
        void printInfo();
        void setInfo(const string & name_, const string & id_,
                     int age_, char gender_);
        string getName(){return name;}
};
void Student::printInfo(){
    cout << "name:" << name << endl;
    cout << "id:" << id << endl;
    cout << "gender:" << gender << endl;
    cout << "age:" << age << endl;
}
void Student::setInfo(const string & name_, const string & id_,
                     int age_, char gender_){
    name = name_;
    id = id_;
    age = age_;
    gender = gender_;
}

class UndergraduateStudent:public Student{  // Undergraduate class, inherits Student class
    private:
        string department; // Name of the Department to which the student belongs
    public:
        void qualifiedForBaoyan(){ // Grant qualifications for research
            cout << "qulified for baoyan" << endl;
        }
        void printInfo(){
            // If you don't write it, it's treated as a derived class's own function
            Student::printInfo(); // Call printInfo of base class
            cout << "Department:" << department << endl;
        }
        void setInfo(const string & name_, const string & id_,
            int age_, char gender_, const string & department_){
            Student::setInfo(name_, id_, age_, gender_); // Call setInfo of base class
            department = department_;
        }
};

int main(){
    UndergraduateStudent s2;
    s2.setInfo("Harry Potter", "118829212", 19, 'M', "Computer Science");
    cout << s2.getName() << " ";
    s2.qualifiedForBaoyan();
    s2.printInfo();
    return 0;
}

There are two functions in the video that were not written, so there was a problem running them, and then I supplemented them with results, as follows:

1.2 Inheritance and Composite Relationships

_Inheritance is a yes-relationship and composite is a yes-relationship.For example, to write a class of circles and points.There is a little bit inside the circle, so I want to write a composite relationship as follows

class Point{
	double x, y;
	friend class Circle; // Because x, y is private
}

class Circle{
	double r;
	Point center;  // Composite Class
}

_Use of a composite relationship: For example, if there is an owner and a dog management information situation, it can only be written in a composite relationship, where each owner has a maximum of 10 dogs, so it is defined as follows:

// Write an object pointer for the Dog class for the Owner class;
// Set up an array of object pointers for the Dog class for the Owner class.
class Master; // Master must be declared in advance and cannot write Master class before Dog class

class Dog{
	Master * pm;
}
class Master{
	Dog * dogs[10];
}
// The two classes can then be independent of each other or find their relationship

1.3 Coverage and Protection of Members

Overrides: Derived classes can define a member with the same name as a base class member, which is called overrides.When accessing such members in a derived class, the default is to access the members of the derived class definition.To access members of the base class with the same name in a derived class, use the domain::.
In general, base and derived classes do not define member variables with the same name.
Protected members of class_are summarized below.

For example,

#include <iostream>
#include <string>
using namespace std;

class Father{
	private: int Private;
	public: int Public;
	protected: Protected;
};
class Son:Father{
	void accessFather(){
		Public = 1;  // Yes?
		Private = 1;  // May not
		Protected = 1;  // Yes, access protected members inherited from the base class
		Son f;  // Not quite understood
		f.Protected = 1; // Error compiling, f is not the current object
	}
}

int main(){
	Father f;
	Son s;
	f.Public = 1; // Yes?
	f.Private = 1; // May not
	f.Protected = 1; // May not

	s.Public = 1; // Yes?
	s.Protected = 1; // May not
	s.Private = 1; // May not
	
	return 0;
}

Constructor for 1.4 Derived Classes

For example,

#include <iostream>
#include <string>
using namespace std;

class Bug{
	private:
		int legs;
		int color;
	public:
		int type;
		Bug(int nlegs, int ncolor);
		void printBug(){};
};
class flyBug: public Bug{
	int wings;
	public:
		flyBug(int nlegs, int ncolor, int nwings);
};
Bug::Bug(int nlegs, int ncolor){
	legs = nlegs;
	color = ncolor;
}
// Wrong flyBug constructor
/*
flyBug::flyBug(int nlegs, int ncolor, int nwings){
	legs = nlegs;  // Not accessible
	color = ncolor; // Not accessible
	type = 1; // Yes?
	wings = nwings; // Yes?
}*/
// Correct flyBug constructor
flyBug::flyBug(int nlegs, int ncolor, int nwings):Bug(nlegs, ncolor){
	wings = nwings; // Yes?
}

int main(){
	flyBug fb(2, 3, 4);
	fb.printBug();
	fb.type = 1;
	// fb.Legs = 2; //Error, Private
	return 0;
}

_When creating an object of a derived class, you need to call the constructor of the base class: initialize the members inherited from the base class in the derived class object.Always execute the constructor of the base class before executing a constructor of a derived class.
There are two ways to call a base class constructor,

Display as follows: In the constructor of a derived class, provide parameters to the constructor of the base class;
        derived::derived(arg_derived-list):base(arg_base-list)
Implicit: In the constructor of a derived class, when the base class constructor is omitted, the constructor of the derived class automatically calls the default constructor of the base class.

When the destructor of a derived class is executed, the constructor of the base class is automatically called after the destructor of the derived class is executed.for example

#include <iostream>
#include <string>
using namespace std;

class Base{
	public:
		int n;
		Base(int i):n(i){
			cout << "Base " << n << " constructed" << endl;
		}
		~Base(){
			cout << "Base " << n << " destructed" << endl;
		}
};
class Derived: public Base{
	public:
		Derived(int i):Base(i){
			cout << "Derived constructed" << endl;
		}
		~Derived(){
			cout << "Derived destructed" << endl;
		}
};
int main(){
	Derived Obj(3);
	return 0;
}

_The results are as follows:

_Contains constructor writings for derived classes of member objects as follows

#include <iostream>
#include <string>
using namespace std;

class Bug{
	private:
		int legs;
		int color;
	public:
		int type;
		Bug(int nlegs, int ncolor);
		void printBug(){};
};
class Skill{
	public:
		Skill(int n){}
};
class flyBug:public Bug{
	int wings;
	Skill sk1, sk2;  // Derived classes containing member objects
	public:
		flyBug(int nlegs, int ncolor, int nwings);
};
flyBug::flyBug(int nlegs, int ncolor, int nwings):
	Bug(legs, color), sk1(5), sk2(color), wings(nwings){
}

1.5 Assignment Compatibility Rules for Public Inheritance

The assignment compatibility rules inherited by public,

class base{};
class derived:public base{};
base b;
derived d;

// 1) Objects of derived classes can be assigned to base class objects
b = d; // d Copy what's inside to b
// 2) Objects of derived classes can initialize base class references
base & br = d; // Base class references the part of a derived class that contains
// 3) Object addresses of derived classes can be assigned to base class pointers
base * bp = & d; // The pointer points to the part of the derived class that contains it (the base class, then the derived class) 
  1. Objects of derived classes can be assigned to base class objects
    b = d; //D Copy what's inside to b
  2. Objects of derived classes can initialize base class references
    Base & br = d; //Base class references the part of a derived class that contains
  3. Object addresses of derived classes can be assigned to base class pointers
    Base * BP = & d; //The pointer points to the part of the derived class that contains it (the base class, then the derived class)
    If it were not public, it would not be true
    _Understanding of direct and indirect base classes.B:A, C:B, D:C, multiple inheritances, easy to understand.
    ------------"Derived classes automatically inherit their indirect base classes up along the class hierarchy.
    ----------"Derived class members include: derived class own members, all members of direct base class, all members of indirect base class
    -------------- When declaring a derived class, you only need to list its direct base class.
    The constructor executes from the base class to the bottom class, starting at the top level.Bottom-to-top destructor execution

2. Virtual Functions and Polymorphisms

2.1 Virtual Functions and Polymorphic Definitions

_In the definition of a class, a member function preceded by the virtual keyword is a virtual function.The virtual keyword is only used for function declarations in class definitions, not for function bodies.Constructors and static member functions cannot be virtual functions.for example

// Virtual functions can participate in polymorphism, other functions cannot
class base{
	virtual int get();
};
int base::get(){}

The first is the representation of polymorphism.
----"Derived class pointers can be assigned to base class pointers;
----) When calling a dummy function of the same name in a base class and a derived class through a base class pointer: 1) If the pointer points to an object of a base class, it is called a dummy function of the base class;2) If the pointer points to an object of a derived class, then the virtual function of the derived class is called. **This mechanism is called polymorphism. **For instance,

class Base{
	public:
		virtual void someVirtualFunc(){}
};
class Derived: public Base{
	public:
		virtual void someVirtualFunc(){}
};

int main(){
	Derived derived;
	Base *p = & derived;
	// Which virtual function to call depends on what type of object p points to
	// Virtual function pointing to Derived class object
	p -> someVirtualFunc();
	return 0;
}

The second is the manifestation of polymorphism.
----"Objects of derived classes can be assigned to base class references
----) When calling a dummy function of the same name in a base class and a derived class through a base class reference: 1) If the reference refers to an object of a base class, then the dummy function of the base class is called;2) If the reference refers to an object of a derived class, then the virtual function of the derived class is called.This mechanism is also called polymorphism.For instance,

class Base{
	public:
		virtual void someVirtualFunc(){}
};
class Derived: public Base{
	public:
		virtual void someVirtualFunc(){}
};

int main(){
	Derived derived;
	Base & r = derived;
	// Which virtual function to call depends on what type of object r refers to
	// Virtual function pointing to Derived class object
	r.someVirtualFunc();
	return 0;
}

A simple example of polymorphism,

#include <iostream>
#include <string>
using namespace std;

class A{
    public:
        virtual void print(){
            cout << "A::print"<<endl;
        }
};
class B: public A{
    public:
        virtual void print(){
            cout << "B::print"<<endl;
        }
};
class D: public A{
    public:
        virtual void print(){
            cout << "D::print"<<endl;
        }
};
class E: public B{
    public:
        virtual void print(){
            cout << "E::print"<<endl;
        }
};

int main(){
    A a; B b;   E e; D d;
    A * pa = & a; B * pb = & b;
    D * pd = & d; E * pe = & e;

    pa -> print(); // pa is a class pointer, polymorphic
    pa = pb;
    pa -> print();
    pa = pd;
    pa -> print();
    pa = pe;
    pa -> print();
    return 0;
}


  
Role of polymorphism: The use of polymorphism in object-oriented programming can enhance the extensibility of the program, i.e. fewer code changes and additions are required when the program needs to modify or add functionality.

2.2 Polymorphic Example: Heroes of the Magic Gate are Invincible

There are many kinds of monsters in the game. Each kind of monster has a class corresponding to it, and each monster is an object.Monsters can attack each other, attacking enemies and being attacked all have corresponding actions, which are achieved through the member function of the object.
When the game version is upgraded, a new monster, Thunderbird, will be added.How can I program so that the code changes and additions during the upgrade are small?
_Basic ideas:
----"Write Attack, FightBack and Hurted member functions for each monster
----"Attack function expresses an attack action, attacks a monster, and calls the Hurted function of the attacked monster to reduce the life value of the attacked monster. It also calls the FightBack member function of the attacked monster to be attacked by the attacked monster.
----"Set the base class Creature, using monsters that are derived from the base class
  
  
_Non-polymorphic Writing:

#include <iostream>
#include <string>
using namespace std;

class Creature{
    protected:
        int power;   // Represents Vitality
        int lifeValue;  // Represents the value of life
};
class Deagon: public Creature{
    public:
        void Attack(Wolf* pWolf){
            // ...code that represents an attack
            pWolf -> Hurted(power);
            pWolf -> FightBack(this);
        }
        void Attack(Ghost* pGhost){
            // ...code that represents an attack
            pGhost -> Hurted(power);
            pGhost -> FightBack(this);  // Point to Attack Initiator
        }
        void Hurted(int power){
            // ...showing an injured action
            lifeValue -= power;
        }
        void FightBack(Wolf* pWolf){
            // ... act as a counterattack
            pWolf -> Hurted(power / 2);
        }
        void FightBack(pGhost* pGhost){
            // ... act as a counterattack
            pGhost -> Hurted(power / 2);
        }
};

_Thus, with monsters in n, there will be n Attack member functions in the Deagon class, and N FightBack member functions.The same is true for other classes.
  
  
_Polymorphic Writing:

#include <iostream>
#include <string>
using namespace std;

class Creature{
    protected:
        int power;   // Represents Vitality
        int lifeValue;  // Represents the value of life
    public:
        virtual void Attack(Creature * pCreature){}
        virtual void Hurted(int power){}
        virtual void FightBack(Creature * pCreature){}
};
class Dragon: public Creature{
    public:
        virtual void Attack(Creature * pCreature);
        virtual void Hurted(int power);
        virtual void FightBack(Creature * pCreature);
};
void Dragon::Attack(Creature * pCreature){
    // ...code that represents an attack
    pCreature -> Hurted(power);  // polymorphic
    pCreature -> FightBack(this);  // polymorphic
}
void Dragon::Hurted(int power){
    // ...showing an injured action
    lifeValue -= power;
}
void Dragon::FightBack(Creature * pCreature){
    // ... act as a counterattack
    pCreature -> Hurted(power / 2);  // polymorphic
}

_If the game is upgraded, new monsters will be added.As long as you write a new kind of monster, you don't need to add member functions to the existing classes for the new monsters. Existing classes can remain intact.The principle is as follows:

#include <iostream>
#include <string>
using namespace std;

// for example
Dragon dragon;    Wolf wolf;   Ghost ghost;
thunderBird Bird;
Dragon.Attack(& wolf);  // (1)
Dragon.Attack(& ghost);  // (2)
Dragon.Attack(& Bird);  // (3)

_According to the polymorphic rule, the above (1), (2), (3) can be called after entering the Dragon::Attack function: Wolf::Hurted, Ghost::Hurted, thunderBird::Hurted.

2.3 Polymorphic example: Geometry program

Geometry Handler: Enter parameters for several geometries, requiring output to be sorted by area.When outputting, specify the shape.

Input:
The first row is the number of geometries n (No more than 100).Below are n Lines, one letter per line c Start.
as c yes "R", Represents a rectangle followed by two integers, the width and the height of the rectangle.
as c yes "C", Represents a circle, followed by an integer representing its radius;
as c yes "T", Represents a triangle, followed by three integers, representing the length of three edges;

Output:
Output the type and area of each geometry in order of area from large to small.One geometry per line with output format:
Body name: Area

Sample Input:
3
R 3 5
C 9
T 3 4 5

Sample Output:
Triangle: 6
Rectangle: 15
Circle: 254.32

_is implemented as follows:

#include <iostream>
#include <stdlib.h>
#include <math.h>

using namespace std;

class Shape{
    public:
        virtual double Area() = 0; // Pure virtual function
        virtual void printInfo() = 0;
};
class Rectangle: public Shape{
    public:
        double w, h;
        virtual double Area();
        virtual void printInfo();
};
class Circle: public Shape{
    public:
        double r;
        virtual double Area();
        virtual void printInfo();
};
class Triangle: public Shape{
    public:
        double a, b, c;
        virtual double Area();
        virtual void printInfo();
};
double Rectangle::Area(){
    return w * h;
}
void Rectangle::printInfo(){
    cout << "Rectangle:" << Area() << endl;
}
double Circle::Area(){
    return 3.14 * r * r;
}
void Circle::printInfo(){
    cout << "Circle:" << Area() << endl;
}
double Triangle::Area(){
    double p = (a + b + c) / 2.0;
    return sqrt(p * (p - a)*(p - b)*(p - c));
}
void Triangle::printInfo(){
    cout << "Triangle:" << Area() << endl;
}

// Array element pointer entered
int myCompare(const void * s1, const void * s2){
    double a1, a2;
    Shape ** p1; // s1, s2 is void*, not writable'*s1'to get what S1 points to
    Shape ** p2;
    p1 = (Shape **)s1; // s1, s2 points to the element in the Shape array whose type is Shape*
    p2 = (Shape **)s2; // p1, p2 are pointers to pointers, of type Shape**
    a1 = (*p1) -> Area(); // *p1 is of type Shape*, is a class pointer, so this sentence is polymorphic
    a2 = (*p2) -> Area();
    if(a1 < a2)return -1;
    else if(a2 < a1)return 1;
    else return 0;
}

Shape * pShapes[100];
int main(){
    int i; int n;
    Rectangle * pr; Circle * pc; Triangle * pt;
    cin >> n;
    for(i = 0; i < n; i++){
        char c;
        cin >> c;
        switch(c){
        case 'R':
            pr = new Rectangle();
            cin >> pr->w >> pr->h;
            pShapes[i] = pr;
            break;
        case 'C':
            pc = new Circle();
            cin >> pc->r;
            pShapes[i] = pc;
            break;
        case 'T':
            pt = new Triangle();
            cin >> pt->a >> pt->b >> pt->c;
            pShapes[i] = pt;
            break;
        }
    }
    qsort(pShapes, n, sizeof(Shape*), myCompare);
    for(i = 0; i < n; i++)
        pShapes[i]->printInfo();
    return 0;
}

_The results are as follows:

2.4 Polymorphic instances: Base example

_Next, to understand this example,

#include <iostream>
#include <stdlib.h>
#include <math.h>

using namespace std;

class Base{
	public:
	    void func1(){func2()}; 
	    /* Explain as follows
		void func1(){this->func2()}; // this Is a class function, fun2 is a virtual function, so it is polymorphic */
	virtual void fun2(){cout << "Base::func2()" << endl};
};
class Derived: public Base{
	public:
		virtual void func2(){cout << "Derived: fun2()" << endl;}
};
int main(){
	Derived d;
	Base *pBase = &d;
	pBase -> fun1();
	return 0;
}

_Next, I want to understand this example, but I really want to exclude that the teacher drinks a real drop of LiuPi, a large bottle of water is really finished, a large bottle...Look below.

_Continue to understand why the output is Derived: fun2(). Note the this pointer.Note that it is polymorphic to call a virtual function in a member function that is not a constructor or a destructor.

Virtual functions are called in_constructors and destructors.Calling virtual functions in constructors and destructors is not polymorphic.At compile time, you can determine that the function you call is a function defined in your own class or base class, and you will not wait until run time to decide whether to call your own or derived class functions.For example,

  
  
_Note that functions in derived classes that have the same parameter table name as virtual functions in base classes automatically become virtual functions without virtual.
  
  

#include <iostream>
#include <stdlib.h>
#include <math.h>

using namespace std;

class myclass{
	public:
		virtual void hello(){cout << "hellp from myclass" << endl;};
		virtual void bye(){cout << "bye from myclass" << endl;}
};
class son:public myclass{
	public:
		// Note: Functions with the same parameter table name as virtual functions in derived classes and base classes automatically become virtual functions without virtual
		void hello(){cout << "hello from son" << endl;};
		// Note that calling virtual functions in constructors and destructors is not polymorphic.
		son(){hello();};  // virtual function
		~son(){bye();};  // virtual function
};
class grandson: public son{
	public: 
	    // Virtual functions, note that calling virtual functions in constructors and destructors is not polymorphic.
		void hello(){cout << "hello from grandson" << endl;};
		void bye(){cout << "bye from grandson" << endl;};
		
		grandson(){cout << "constructing grandson" << endl;};
		~grandson(){cout << "distructing grandson" << endl;};
};

int main(){
	grandson gson;
	son * pson;
	pson = &gson;
	pson -> hello();  // polymorphic
	return 0;
}

_The results are as follows:

3. Principles of polymorphic implementation, etc.

There are two more subsections to make up for tomorrow.

4. Summary

_This teacher is really good at speaking, has clear logic, does not card BUG for repetition according to what he says, does not waste time adjusting, just understand it directly. I really recommend you to watch his video if you want to learn.In the last two days, I sent my resume, got a written test and interview, but the result is not very ideal.I have not learned enough by myself. Keep going.And I have also changed the content of the next second paper in the past two days, which is how I feel.To tell the truth, for my own reasons and D S reasons, I really don't like my topic right now. The paper just doesn't want to change, just like EX.The first paper teacher made me change from March to September, the process is more complex, and I have not yet contributed, from worry, tiredness, pain to the present indifference, after which graduation is OK.Anyway, I feel that now I have the motivation to learn and continue to do it.Something may have happened recently. The third edition may be slower or the liver may run out quickly.

Tags: C++ Polymorphism

Posted on Thu, 02 Sep 2021 12:38:48 -0400 by deathrider