继承与派生类Circle and Rectangle和The Person, Student, Employee, Faculty and Staff Class
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了继承与派生类Circle and Rectangle和The Person, Student, Employee, Faculty and Staff Class相关的知识,希望对你有一定的参考价值。
C++为了更加的灵活,更加是程序员自由随性的编写程序,定义了类类型。我们在其中自定义类型,在其中封装函数,甚至在其中重载运算符来改变其原有的属性。类的继承又将类应用的更加开拓。我们用类来使用原有的类,充分体现了C++的开放与包容
派生类(或子类,继承类)拥有基类(或父类,超类)的所有属性及行为,又定义了自己的属性及行为,派生类能够访问基类,但基类就没有访问派生类的权限。二者的关系并不可逆。基类是派生类的抽象,派生类是基类的具体化。从一个基类派生出来的叫做单继承,从多个基类派生出来的叫做多继承。由一个基类派生出多个子类的派生方法叫多重派生,派生类又作为基类继续派生的派生方法叫做多层派生。所以单继承、多继承、多重派生、多层派生所谈论的对象是不同的,单继承和多继承说派生类,多重派生和多层派生说基类。
类的继承有三种方式,公有继承方式,私有继承方式,保护继承方式,对应类中的三种数据成员,public,private,protected,(protected与private的区别在这里体现并只在这里体现,在以往的类讨论中总把他们的访问权限看做一致)并对应产生了三种派生类的定义。
派生类的定义格式为class 派生类名:继承方式 基类名{};
不同继承方式的影响在两个方面
1.派生类成员对于基类成员的访问控制。
2.派生类对象对于基类成员的访问控制。
单继承:
派生类构造函数只需要对本类新增的数据成员进行初始化,对于积累数据成员的初始化调用基类的构造函数自行初始化。派生类的构造函数包含不少于基类构造函数个数的形参并通过初始化列表调用基类构造函数,但如果基类没有定义构造函数或者定义了含有默认形参(或没有形参或缺省)的构造函数,则派生类不必调用基类的构造函数。如果派生类中还含有子对象,则还应包含子对象初始化的构造函数。派生类的构造函数定义格式如下:
派生类名:(基类数据成员,本类数据成员):基类构造函数(参数表1),子对象名(参数表2){派生类中的数据成员初始化};
派生类对象中由基类中说明的数据成员和操作构成的封装体成为基类子对象。
一:公有继承
在一般类中,public成员可以由外部对象直接访问,也可以由内部的成员函数相互调用,而private和protected则是对外信息隐蔽,他们只能由public成员调用,最具代表性的就是访问器和突变器。定义派生类之后,基类的public成员可以由基类的外部对象,基类的成员函数,派生类的外部对象,派生类的成员函数访问;基类的protected成员可以由基类的public成员,派生类的成员函数访问,不能由基类的外部对象访问,不能由派生类的外部对象访问;基类的private成员可以由基类的public成员函数访问,不能由基类的外部对象访问,不能由派生类的外部对象访问,不能由派生类的成员函数访问(可见,他们的访问权限是依次增强的)。派生类的public可以由派生类的成员,派生类的外部对象直接访问,protected可以由public成员访问,不能由派生类的外部对象直接访问,同样,private也可以由派生类public成员访问,不能由派生类的外部对象访问。
举例:
#include<iostream> #include<cstring> using namespace std; class Person{ private: char name[10]; int age; char sex; public: void Init_Person(char*str,int age1,char s); void print(); }; void Person::Init_Person(char*str,int age1,char s){ strcpy(name,str); age=age1; sex=s; } void Person::print(){ cout<<"\\n"<<name<<" "<<age<<" "<<sex<<" "; } class Student:public Person{ private: int class_no; int score; public: void Init_Student(char*str2,int age2,char s2,int c_no,int score1); void show_st(); }; void Student::Init_Student(char*str2,int age2,char s2,int c_no,int score1){ Init_Person(str2,age2,s2); class_no=c_no; score=score1; } void Student::show_st(){ print(); cout<<class_no<<score<<endl; } int main(){ Student st; st.Init_Person("Li Ping",18,‘F‘); st.print(); st.Init_Student("Li Ping",18,‘F‘,1,98); st.show_st(); }
二.私有继承
私有继承以后,基类中的public成员和protected成员成为派生类中private成员,这意味着对于派生类来说,基类的所有数据成员相当于派生类的
私有数据成员。基类private成员只能由基类的public成员函数访问,基类的外部对象,派生类的外部对象,派生类的成员函数都不能访问它;基类的protected成员可以由基类的public成员函数,,派生类的public成员函数访问,基类的外部对象,派生类的外部对象都不能访问它;基类的public成员可以由基类的外部对象,基类的public成员函数,派生类的public成员函数访问,派生类的外部对象不能访问它。也就是说,三种数据成员都不能由派生类的外部对象访问,这体现了private继承方式的信息隐藏。
#include<iostream> #include<cstring> using namespace std; class Person{ private: char name[10]; int age; char sex; public: void Init_Person(char*str,int age1,char s); void print(); }; void Person::Init_Person(char*str,int age1,char s){ strcpy(name,str); age=age1; sex=s; } void Person::print(){ cout<<"\\n"<<name<<" "<<age<<" "<<sex<<" "; } class Student:private Person{ private: int class_no; int score; public: void Init_Student(char*str2,int age2,char s2,int c_no,int score1); void show_st(); }; void Student::Init_Student(char*str2,int age2,char s2,int c_no,int score1){ Init_Person(str2,age2,s2); class_no=c_no; score=score1; } void Student::show_st(){ print(); cout<<class_no<<score<<endl; } int main(){ Person p; Student st; p.Init_Person("Li Ping",18,‘F‘); p.print(); st.Init_Student("Li Ping",18,‘F‘,1,98); st.show_st(); }
三.保护继承
当类的继承方式为protected时,基类的public成员和protected成员都作为派生类的protected成员,派生类的其它数据成员可以直接访问它们,但是派生类的外部对象不能直接访问。也即,基类的public成员可以由基类外部对象,基类public成员函数,派生类public成员函数访问,不能由派生类外部对象访问;基类private成员可以由基类public成员函数访问,不能由基类外部对象,派生类外部对象,派生类public成员函数访问;基类protected成员可以由基类public成员函数,派生类public成员函数访问,不能由派生类外部成员,派生类public成员函数访问。
#include<iostream> #include<cstring> using namespace std; class Person{ private: char name[10]; int age; char sex; public: void Init_Person(char*str,int age1,char s); void print(); }; void Person::Init_Person(char*str,int age1,char s){ strcpy(name,str); age=age1; sex=s; } void Person::print(){ cout<<"\\n"<<name<<" "<<age<<" "<<sex<<" "; } class Student:protected Person{ private: int class_no; int score; public: void Init_Student(char*str2,int age2,char s2,int c_no,int score1); void show_st(); }; void Student::Init_Student(char*str2,int age2,char s2,int c_no,int score1){ Init_Person(str2,age2,s2); class_no=c_no; score=score1; } void Student::show_st(){ print(); cout<<class_no<<score<<endl; } int main(){ Person p; Student st; p.Init_Person("Li Ping",18,‘F‘); p.print(); st.Init_Student("Li Ping",18,‘F‘,1,98); st.show_st(); }
由以上可见,private数据成员最具信息隐藏性,无论怎样继承,它总是除了基类的public成员函数其余都不能直接访问。public最方便继承与数据共享,protected数据成员既可以实现数据隐藏,又方便继承,最高效的实现了实现代码重用,两者的优点兼备,这也是C++定义protected的好处。
实验课代码Circle and Rectangle
代码要求:
代码实现:
#include<iostream> #include<string> #include<cmath> using namespace std; class Point{ private: double x,y; public: Point(); Point(double xv,double yv); Point(Point& pt); double getx(){return x;}; double gety(){return y;}; }; Point::Point(){ x=0; y=0; } Point::Point(double xv,double yv){ x=xv; y=yv; } Point::Point(Point& pt){ x=pt.x; y=pt.y; }; class Circle:public Point{ public: Circle(){ radius=0; }; Circle(double xv,double yv,double r):Point(0,0){ x=xv; y=yv; radius=r; }; int position(Point &pt){ double i=sqrt((x-pt.getx())*(x-pt.getx())+(y-pt.gety())*(y-pt.gety())); if(i>radius)return 1; if(i<radius)return -1; if(i=radius)return 0; }; private: double x; double y; double radius; }; class Rectangle:public Point{ public: Rectangle(){ x=0; y=0; len=0; wid=0; }; Rectangle(double xv,double yv,double l,double w):Point(0,0){ x=xv; y=yv; len=l; wid=w; }; int position(Point &pt){ if((pt.getx()-x)>0&&(pt.getx()-x)<len&&(pt.gety()-y)>0&&(pt.gety()-y)<wid)return -1; if((pt.getx()-x==0)||(pt.getx()-x==len)){ if((pt.gety()-y)>=0&&(pt.gety()-y<=wid))return 0; } if((pt.gety()-y==0)||(pt.gety()-y==wid)){ if((pt.getx()-x)>=0&&(pt.getx()-x<=len))return 0; } return 1; } private: double x; double y; double len; double wid; };
用于调试的主函数:
#include <iostream> #include <fstream> #include <cmath> using namespace std; #include "source.h" const double PI=3.14; int main(){ //freopen("test02.out", "w", stdout); Circle cc1(3,4,5),cc2,cc3(cc1); Rectangle rt1(0,0,6,8),rt2,rt3(rt1); Point p1(0,0),p2(6,8),p3(3,3),p4(8,4),p5(8,8); // cc1.Show(); // cc2.Show(); // rt1.Show(); // rt2.Show(); cout<<"point p1:"; // p1.Show(); // cout<<"矩形rt3:"<<‘\\t‘; // rt3.Show(); switch(rt3.position(p1)){ case 0:cout<<"on-rectangle"<<endl;break; case -1:cout<<"inside-rectangle"<<endl;break; case 1:cout<<"outside-rectangle"<<endl;break; } // cout<<"圆cc3:"<<‘\\t‘; // cc3.Show(); switch(cc3.position(p1)){ case 0:cout<<"on-circle"<<endl;break; case -1:cout<<"inside-circle"<<endl;break; case 1:cout<<"outside-circle"<<endl;break; } cout<<"point p2:"; // p2.Show(); // cout<<"矩形rt3:"<<‘\\t‘; // rt3.Show(); switch(rt3.position(p2)){ case 0:cout<<"on-rectangle"<<endl;break; case -1:cout<<"inside-rectangle"<<endl;break; case 1:cout<<"outside-rectangle"<<endl;break; } // cout<<"圆cc3:"<<‘\\t‘; // cc3.Show(); switch(cc3.position(p2)){ case 0:cout<<"on-circle"<<endl;break; case -1:cout<<"inside-circle"<<endl;break; case 1:cout<<"outside-circle"<<endl;break; } cout<<"point p3:"; // p3.Show(); // cout<<"矩形rt3:"<<‘\\t‘; // rt3.Show(); switch(rt3.position(p3)){ case 0:cout<<"on-rectangle"<<endl;break; case -1:cout<<"inside-rectangle"<<endl;break; case 1:cout<<"outside-rectangle"<<endl;break; } // cout<<"圆cc3:"<<‘\\t‘; // cc3.Show(); switch(cc3.position(p3)){ case 0:cout<<"on-circle"<<endl;break; case -1:cout<<"inside-circle"<<endl;break; case 1:cout<<"outside-circle"<<endl;break; } cout<<"point p4:"; // p4.Show(); // cout<<"矩形rt3:"<<‘\\t‘; // rt3.Show(); switch(rt3.position(p4)){ case 0:cout<<"on-rectangle"<<endl;break; case -1:cout<<"inside-rectangle"<<endl;break; case 1:cout<<"outside-rectangle"<<endl;break; } // cout<<"圆cc3:"<<‘\\t‘; // cc3.Show(); switch(cc3.position(p4)){ case 0:cout<<"on-circle"<<endl;break; case -1:cout<<"inside-circle"<<endl;break; case 1:cout<<"outside-circle"<<endl;break; } cout<<"point p5:"; // p5.Show(); // cout<<"矩形rt3:"<<‘\\t‘; // rt3.Show(); switch(rt3.position(p5)){ case 0:cout<<"on-rectangle"<<endl;break; case -1:cout<<"inside-rectangle"<<endl;break; case 1:cout<<"outside-rectangle"<<endl;break; } // cout<<"圆cc3:"<<‘\\t‘; // cc3.Show(); switch(cc3.position(p5)){ case 0:cout<<"on-circle"<<endl;break; case -1:cout<<"inside-circle"<<endl;break; case 1:cout<<"outside-circle"<<endl;break; } return 0; }
多继承:
多继承可以看做是单继承的扩展,其定义格式如下:
class 派生类名:继承方式1 基类名1,继承方式2 基类名2,……继承方式n 基类名n{};
每一个继承方式都只对于紧随其后的基类而言。
举例如下:
#include<iostream> using namespace std; class Point{ private: int x,y; public: void SetPoint(int x1,int y1){x=x1;y=y1} void print(){cout<<"("<<x<<","<<y<<")";} }; class Line{ private: int x1,y1,x2,y2; public: void SetLine(int a1,int b1,int,a2,int b2){ x1=a1;y1=b1;x2=a2;y2=b2;} void print(){ cout<<"("<<x1<<","<<y1<<")"; cout<<"("<<x<<","<<y<<")";} }; class Box:public Point,public Line{ public: void printp(){Point::print();} void printl(){Line::print();} int main(){ Box tb; tb.SetPoint(2,8); cout<<"PointXY:"<<; tb.printp(); cout<<"\\nPointLine:"; tb.SetLine(2,8,12,16);
tb.printL();
}
多继承的构造函数:
多继承的构造函数的格式:
派生类名::派生类名(基类1形参,基类2形参,基类3形参……基类n形参,本类形参):基类名1(参数),基类名2(参数),……基类名n(参数),对象数据成员的初始化{本类成员初始化赋值语句;};
当基类定义中定义有默认形参的构造函数或未定义构造函数时,派生类构造函数定义中可以省略对基类构造函数的调用。当基类构造函数中有形参时,派生类必须有构造函数且构造函数中应该有不少于基类构造函数形参个数的形参,借以提供基类数据成员的得以初始化的途径。当然,有子对象时,要先实现子对象的初始化。
实验课代码The Person, Student, Employee, Faculty and Staff Class
代码要求:
代码实现:
#include <iostream> #include <string> using namespace std; class Person{ private: string name,address,phoneNumber,email; public: virtual string toString(){ //定义虚函数,说明之后派生类中还会有同名且形参个数和类型完全相同只有操作不同的函数。涉及到虚函数的性质。 return "Person"; } }; class Student:public Person{ public: enum class_status{frssman,sophomore,junior,senior}; class_status status; string toString(){ return "Student"; } }; class Employee:public Person{ public: string office; int salary; string toString(){ return "Employee"; } }; class Faculty:public Employee{ public: string officeHours; int rank; string toString(){ return "Faculty"; } }; class Staff:public Employee{ public: string title; string toString(){ return "Staff"; } };
用于调试的主函数:
#include <iostream> #include <string> #include "source.h" using namespace std; void f1(Person p) { cout << p.toString() << endl; } void f2(Employee e) { cout << e.toString() << endl; } void f(Person &p) { cout << p.toString() << endl; } int main() { Person person; Student student; Employee employee; Faculty faculty; Staff staff; f1(person); f1(student); f1(employee); f1(faculty); f1(staff); f2(employee); f2(faculty); f2(staff); f(person); f(student); f(employee); f(faculty); f(staff); return 0; }
以上是关于继承与派生类Circle and Rectangle和The Person, Student, Employee, Faculty and Staff Class的主要内容,如果未能解决你的问题,请参考以下文章