8113
备注:
|
11125
|
删除的内容标记成这样。 | 加入的内容标记成这样。 |
行号 152: | 行号 152: |
继承和组合是软件复用的两种方式。 |
|
行号 245: | 行号 247: |
类的完整实现实例: {{{#!cplusplus class Person { string name; bool gender; public: Person(string n, bool g) : name(n), gender(g) { } }; class Teacher : public Person { int salary; int level; public: Teacher(string n, bool g, int s, int l) : Person(n, g), salary(s), level(l) { } }; class Student: public Person { string id; int department; public: Student(string n, bool g, string i, int d) : Person(n, g), id(i), department(d) { } }; class GradStudent: public Student { Teacher *tutor; public: GradStudent(string n, bool g, string i, int d, Teacher *t) : Student(n, g, i, d), tutor(t) { } }; }}} |
|
行号 260: | 行号 293: |
int main() { Student s; Person p; } |
|
行号 267: | 行号 304: |
~Person() { cout << "destruct Person" <<endl; } | ~Person() { cout << "destruct Person" << endl; } |
行号 276: | 行号 313: |
} }}} 派生类的构造析构实例。派生类析构函数只负责派生类增加部分的分配资源的析构。 |
Person p; } }}} 派生类析构函数只负责派生类增加部分的分配资源的析构。 |
行号 321: | 行号 359: |
Student &rd = s; Person &rp = p; Student &rd2 = p; //error Person &rp2 = s; // ok |
|
行号 336: | 行号 378: |
在C++中允许一个派生类有多个基类,这种继承叫做多继承。相对的只有一个基类的继承被称为单继承。多继承表达的是“派生类既是一种基类A,又是一种基类B”的逻辑关系。 比如Assistent类继承了Student和Teacher两个类: {{{#!cplusplus class Assistant : public Student, public Teacher { public: Assistant(string n, string i, string l) : Teacher(n, l), Student(n, i) { cout << "a"; } void print() const { cout<< name << id << level; // ambiguous error cout<< Student::name << Teacher::name << id << level; } }; }}} 多继承时对象的复制:派生类对象的指针可以赋给任何一个基类类型的指针 {{{#!cplusplus Assistant assist("jack", "12456", "assistant"); Student s = assist; //OK, slice Teacher t = assist; //OK, slice Student *ps = &assist; //OK Teacher *pt= &assist; //OK ps->print(); pt->print(); Person *p = &assist; //ambigius Person *p = (Student *)&assist; Person *p = (Teacher *)&assist; p->print(); }}} |
|
行号 339: | 行号 413: |
class Person { }; class Student : virtual public Person { }; class Teacher : virtual public Person { }; class Assistant : public Student, public Teacher { }; 虚基类Person在派生类Assistant的对象中只有一份 class Person { string name; public: Person(string n):name(n){ cout << "P"; } }; class Student : virtual public Person { string id; public: Student(string n, string i):id(i), Person(n){ cout<<"S";} }; class Teacher : virtual public Person { string level; public: Teacher(string n, string l):level(l), Person(n){cout<<"T";} }; class Assistant : public Student, public Teacher { public: Assistant(string n, string i, string l) : Student(n, i), Teacher(n, l), Person(n) {cout<<"A";} }; |
|
行号 340: | 行号 445: |
class Derived : private Base { //… }; class Derived: protected Base { //… }; class Base { public: int a; protected: int b; private: int c; }; class Derived : private Base{ void f() { cout << a << b << c; } }; int main() { Derived d; cout << d.a << d.b << d.c; } |
继承
1. 派生类的定义
继承/派生是类的重用的一种方法。继承/派生是指在已有的类的基础上,添加新的成员进行扩充,构成新类的机制。已有的类称为基类/父类,扩充形成的新类称为派生类/子类。父类派生出子类,子类继承了父类。派生类和基类在逻辑生存在is a的关系。比如说,学生Student是一类人Person,老师Teacher也是一类人Person,研究生GraduateStudent是一类学生Student。我们用C++语言来描述这种关系:
1 class Person {
2 private:
3 string name;
4 Date birth;
5 bool gender;
6 };
7
8 //Teacher类继承了Person类
9 class Teacher : public Person
10 {
11 private:
12 int salary;
13 int level;
14 };
15 //Student类继承了Person类,public指明继承方式是公有继承
16 class Student : public Person
17 {
18 private:
19 string ID;
20 int department;
21 };
22 //GradStudent类继承了Student类
23 class GradStudent : public Student {
24 private:
25 Teacher *tutor;
26 };
加上成员函数的实现:
1 class Person {
2 string name;
3 Date birth;
4 bool gender;
5 public:
6 string get_name();
7 Date get_date();
8 bool get_gender();
9 };
10 class Teacher : public Person {
11 int salary;
12 int level;
13 public:
14 int get_salary();
15 int get_level();
16 };
17 class Student: public Person {
18 string ID;
19 int department;
20 public:
21 string get_id();
22 int get_department();
23 };
24 class GradStudent: public Student {
25 Teacher *tutor;
26 public:
27 Teacher *get_tutor();
28 };
派生类对象的定义:
2. 派生类的访问权限
- private成员:只在定义它的类的成员函数中可以访问,在派生类的成员函数中不可访问。基类的私有成员被派生类继承,但是不能被派生类访问
- protected成员:在本类及派生类中能访问的成员。派生类可以访问继承的保护成员,但是不能访问一个基类对象的保护成员
使用using声明改变基类成员权限
派生类的成员名字如果与基类相同,将隐藏基类成员
1 class Person {
2 public:
3 void set(string name);
4 void set(bool gender);
5 };
6 class Student : public Person{
7 public:
8 void set(int department); // hide base member functions
9 };
10 void f(Student &s) {
11 s.set("12345");
12 s.set( true );
13 s.Person::set("12345"); //ok
14 s.Person::set(true); //ok
15 }
继承和组合是软件复用的两种方式。
3. 派生类的构造和析构
创建派生类对象时,基类的构造函数会被自动调用,用于初始化继承下来的基类部分的成员。如果派生类没有构造函数,或者没有显示调用,那么基类中的默认构造函数会被自动调用。
1 class Person {
2 public:
3 Person(string aname = "", bool agender = false) {
4 name = aname; gender = agender;
5 }
6 private:
7 string name;
8 bool gender;
9 };
10 class Student : public Person {
11 private:
12 int department;
13 string id;
14 };
15 int main() {
16 Student d; // default constructor of Person is called
17 }
派生类可以定义自己的构造函数,用于初始化派生类扩展的部分
1 class Person {
2 public:
3 Person(string aname = "", bool agender = false) {
4 name = aname;
5 gender = agender;
6 cout << "Person initialized" << endl;
7 }
8 private:
9 string name;
10 bool gender;
11 };
12 class Student : public Person{
13 int department;
14 string id;
15 public:
16 Student() :department(11), id("0509342") {
17 cout << "Student initialized" << endl;
18 }
19 };
20 int main() {
21 }
在这个派生类的构造函数中,没有给基类的构造函数任何参数,基类中的默认构造函数会被调用。
如果基类的构造函数需要参数,那么需要使用初始化列表为基类构造提供参数。
1 class Person {
2 public:
3 Person(string aname, bool agender) {
4 name = aname;
5 gender = agender;
6 }
7 private:
8 string name;
9 bool gender;
10 };
11 class Student : public Person {
12 public:
13 Student(string name, bool gender, int dep)
14 : department(dep) , Person ( name, gender )
15 {
16 }
17 private:
18 int department;
19 };
在一个多层的继承结构里面,创建一个派生类对象时,所有的基类的构造函数都会被调用。
1 class Person {
2 public:
3 Person( ) { cout << "construct Person"; }
4 };
5 class Student : public Person {
6 public:
7 Student( ) { cout << "construct Student"; }
8 };
9 class GradStudent : public Student {
10 public:
11 GradStudent( ) { cout << "construct GradStudent"; }
12 };
13 int main( ) {
14 GradStudent gs;
15 }
类的完整实现实例:
1 class Person {
2 string name;
3 bool gender;
4 public:
5 Person(string n, bool g) : name(n), gender(g) {
6 }
7 };
8 class Teacher : public Person {
9 int salary;
10 int level;
11 public:
12 Teacher(string n, bool g, int s, int l) : Person(n, g), salary(s), level(l) {
13 }
14 };
15 class Student: public Person {
16 string id;
17 int department;
18 public:
19 Student(string n, bool g, string i, int d) : Person(n, g), id(i), department(d) {
20 }
21 };
22 class GradStudent: public Student {
23 Teacher *tutor;
24 public:
25 GradStudent(string n, bool g, string i, int d, Teacher *t)
26 : Student(n, g, i, d), tutor(t) {
27 }
28 };
派生类对象被销毁时,基类的析构函数会被自动调用。如果派生类和基类都有析构函数,那么他们都会被调用。
派生类构造和析构顺序
1 class Person {
2 public:
3 Person() { cout << "construct Person" << endl; }
4 ~Person() { cout << "destruct Person" << endl; }
5 };
6 class Student : public Person{
7 public:
8 Student() { cout << "construct Student" <<endl; }
9 ~Student() { cout << "destruct Student" <<endl; }
10 };
11 int main() {
12 Student s;
13 Person p;
14 }
派生类析构函数只负责派生类增加部分的分配资源的析构。
1 class Base {
2 public:
3 Base() {
4 s = new char[3];
5 }
6 ~Base() {
7 delete[ ] s;
8 }
9 private:
10 char *s;
11 };
12 class Derived : public Base {
13 public:
14 Derived() {
15 sd = new char[5];
16 }
17 ~Derived () {
18 delete[ ] sd;
19 }
20 private:
21 char *sd;
22 };
23 int main() {
24 Base b;
25 Derived d;
26 }
4. 派生类对象和对象指针的复制
有继承关系的对象复制
1 Student s("jack", Date(1980, 8, 8), true, 970101, 10);
2 Person p = s; //slice
3 Student s = p; //error
4
5 Student *pD = new Student("jack", Date(1980, 8, 8), true, 970101, 10);
6 Person *pB = pD; //correct 基类指针指向派生类对象
7 Person *pB2 = new Student("jack", Date(1980, 8, 8), true, 970101, 10);
8 pB = new Teacher; //多态性在这里体现
9 Student &rd = s;
10 Person &rp = p;
11 Student &rd2 = p; //error
12 Person &rp2 = s; // ok
13
指针类型的转换
5. 多继承
在C++中允许一个派生类有多个基类,这种继承叫做多继承。相对的只有一个基类的继承被称为单继承。多继承表达的是“派生类既是一种基类A,又是一种基类B”的逻辑关系。
比如Assistent类继承了Student和Teacher两个类:
多继承时对象的复制:派生类对象的指针可以赋给任何一个基类类型的指针
1 Assistant assist("jack", "12456", "assistant");
2 Student s = assist; //OK, slice
3 Teacher t = assist; //OK, slice
4 Student *ps = &assist; //OK
5 Teacher *pt= &assist; //OK
6 ps->print();
7 pt->print();
8 Person *p = &assist; //ambigius
9 Person *p = (Student *)&assist;
10 Person *p = (Teacher *)&assist;
11 p->print();
6. 虚基类
class Person { }; class Student : virtual public Person { }; class Teacher : virtual public Person { }; class Assistant : public Student, public Teacher { }; 虚基类Person在派生类Assistant的对象中只有一份
class Person {
- string name;
public:
Person(string n):name(n){ cout << "P"; }
}; class Student : virtual public Person {
- string id;
public:
Student(string n, string i):id(i), Person(n){ cout<<"S";}
}; class Teacher : virtual public Person {
- string level;
public:
Teacher(string n, string l):level(l), Person(n){cout<<"T";}
}; class Assistant : public Student, public Teacher { public:
- Assistant(string n, string i, string l)
: Student(n, i), Teacher(n, l), Person(n) {cout<<"A";}
};
7. 保护继承和私有继承
class Derived : private Base { //… };
class Derived: protected Base { //… };
class Base { public: int a; protected: int b; private: int c; }; class Derived : private Base{
- void f() {
cout << a << b << c;
}; int main() {
- Derived d;
cout << d.a << d.b << d.c;
}
8. 多态与虚函数
9. 纯虚函数和抽象类
10. 运行时类型信息
11. 面向对象设计方法