class 子类名 : public 父类名 { }; /* 示例 */ class Person { }; // Student继承自Person class Student : public Person { };
一个类对象的内存空间 = 全部成员变量所占空间的总和ios
一个子类对象的内存空间 = 全部父类成员变量所占空间的总和 + 自身成员变量所占空间的总和ide
对象所占空间不包含静态成员变量函数
子类中,父类成员变量在内存中的位置靠前测试
类中存在虚函数时,会多出一个指针的空间存放虚函数表的地址,而这个指针位于对象开头this
#include <iostream> using namespace std; class Person { int age; }; class Student : public Person { int id; }; int main() { cout << sizeof(Student) << endl; // 8,两个int cout << sizeof(Person) << endl; // 4,1个int return 0; }
采用初始化列表spa
#include <iostream> using namespace std; class Person { public: int age; Person(int age) : age(age) { } }; class Student : public Person { public: int id; Student(int id, int age) : Person(age), id(id) { } }; int main() { Student student(1, 25); cout << student.id << endl; cout << student.age << endl; return 0; }
建立:父类 -> 子类
消亡:子类 -> 父类指针
#include <iostream> using namespace std; class Person { public: Person() { cout << "Person()" << endl; } ~Person() { cout << "~Person()" << endl; } }; class Student : public Person { public: Student() { cout << "Student()" << endl; } ~Student() { cout << "~Student()" << endl; } }; int main() { Student student; return 0; }
父类名::方法名();code
#include <iostream> using namespace std; class Person { public: int age; void sayHello() { cout << "Hello" << endl; } }; class Student : public Person { public: int id; void sayHello() { Person::sayHello(); cout << "World" << endl; } }; int main() { Student student; student.sayHello(); return 0; }
多态就是父类的指针或引用调用子类的方法或变量对象
#include <iostream> using namespace std; class Person { public: void sayHi() { cout << "Person sayHi" << endl; } }; class Student : public Person { public: void sayHi() { cout << "Student sayHi" << endl; } }; int main() { Student student; Person * pPerson = &student; pPerson->sayHi(); // 打印:Person sayHi Person & rPerson = student; rPerson.sayHi(); // 打印:Person sayHi return 0; }
满心期待上面的代码可以完成多态,结果...尼玛怎么不对!!!继承
原来坑爹C++又整出个虚函数
一个正常的成员函数前加virtual关键字
若是该方法在父类中已经定义为虚函数,那么子类virtual能够省略,但不建议
#include <iostream> using namespace std; class Person { public: void sayHi() { cout << "Person sayHi" << endl; } virtual void sayHello() { cout << "Person sayHello" << endl; } }; class Student : public Person { public: void sayHi() { cout << "Student sayHi" << endl; } void sayHello() { cout << "Student sayHello" << endl; } }; int main() { Student student; Person * pPerson = &student; pPerson->sayHi(); pPerson->sayHello(); // 引用方式调用多态 // Person & rPerson = student; // rPerson.sayHi(); // rPerson.sayHello(); return 0; }
构造函数和析构函数中,能够调用虚函数,但不会出现多态。缘由是父类构造函数调用时,子类成员变量还未初始化,父类析构函数调用时,子类析构函数已经执行完毕。总之若是能够在构造和析构函数中出现多态,是危险的。
#include <iostream> using namespace std; class Person { public: Person() { sayHello(); } virtual void sayHello() { cout << "Person sayHello" << endl; } // 析构函数测试 // ~Person() { // sayHello(); // } }; class Student : public Person { public: Student() { sayHello(); } virtual void sayHello() { cout << "Student sayHello" << endl; } // ~Student() { // sayHello(); // } }; int main() { Student student; return 0; }
当父类指针或引用调用不是虚函数的成员函数,这个成员函数中又调用了虚函数,会出现多态。
#include <iostream> using namespace std; class Person { public: void sayHi() { cout << "Person sayHi" << endl; sayHello(); // 至关于this->sayHello(); 跟在外部用指针调用是一个意思 } virtual void sayHello() { cout << "Person sayHello" << endl; } }; class Student : public Person { public: void sayHi() { cout << "Student sayHi" << endl; sayHello(); } virtual void sayHello() { cout << "Student sayHello" << endl; } }; int main() { Student student; Person * pPerson = &student; pPerson->sayHi(); return 0; }
多态实现的关键是虚函数表
每个有虚函数的类(或是父类中有虚函数) 都有一个虚函数表
该类的对象在内存的开头,存放着一个指针,这个指针指向虚函数表
虚函数表中列出了该类的虚函数地址
#include <iostream> using namespace std; class Person { public: virtual void sayHello() { } }; int main() { // 跟一个指针的大小是同样的 cout << sizeof(Person) << endl; return 0; }
当用父类指针或引用,delete时,只有父类的析构函数会被调用。定义虚析构函数能够解决这个问题。
#include <iostream> using namespace std; class Person { public: ~Person() { cout << "~Person" << endl; } }; class Student : public Person { public: ~Student() { cout << "~Student" << endl; } }; int main() { Person * person = new Student; delete person; return 0; }
在析构函数前加virtual关键字
若是父类的析构函数已经加了virtual,子类中的virtual关键字能够省略,不推荐
#include <iostream> using namespace std; class Person { public: Person() { cout << "Person" << endl; } virtual ~Person() { cout << "~Person" << endl; } }; class Student : public Person { public: Student() { cout << "Student" << endl; } ~Student() { cout << "~Student" << endl; } }; int main() { Person * person = new Student; delete person; return 0; }
纯虚函数: 没有函数体的虚函数
抽象类: 包含纯虚函数的类
非抽象类: 实现全部纯虚函数的类
virtual 返回值 函数名(参数列表) = 0 ;
#include <iostream> using namespace std; class CGeometry { public: virtual ~CGeometry(){ } virtual double calPerimeter() = 0; }; class CTriangle : public CGeometry { public: double side1; double side2; double side3; virtual double calPerimeter() { return side1 + side2 + side3; } }; class CCircle : public CGeometry { public: double radius; virtual double calPerimeter() { return 2 * 3.14 * radius; } }; class CRectangle : public CGeometry { public: double width; double height; virtual double calPerimeter() { return 2 * (width + height); } }; int compare(const void * p1, const void * p2) { int result = 0; CGeometry ** g1 = (CGeometry **)p1; CGeometry ** g2 = (CGeometry **)p2; double perimeter1 = (*g1)->calPerimeter(); double perimeter2 = (*g2)->calPerimeter(); if (perimeter1 > perimeter2) { result = 1; } else if (perimeter1 < perimeter2) { result = -1; } return result; } /* 运行:前四行为输入,后3行为输出 3 R 1 1 C 1 T 1 1 1 3 4 6.28 */ int main() { int number; cin >> number; char type; CGeometry * geometries[number]; CTriangle * pTriangle; CCircle * pCircle; CRectangle * pRectangle; for (int i = 0; i < number; i++) { cin >> type; switch (type) { case 'R': pRectangle = new CRectangle(); cin >> pRectangle->width >> pRectangle->height; geometries[i] = pRectangle; break; case 'C': pCircle = new CCircle(); cin >> pCircle->radius; geometries[i] = pCircle; break; case 'T': pTriangle = new CTriangle(); cin >> pTriangle->side1 >> pTriangle->side2 >> pTriangle->side3; geometries[i] = pTriangle; break; } } qsort(geometries, number, sizeof(CGeometry *), compare); for (int i = 0; i < number; i++) { cout << geometries[i]->calPerimeter() << endl; delete geometries[i]; } return 0; }