类中说明的重载
#include<bits/stdc++.h>using namespace std;/*** 在类中说明的重载* */class Cube {public:Cube() {height = 1;width = 2;length = 3;}Cube(int h, int w, int l) {height = h;width = w;length = l;}private:int height;int width;int length;};int main() {Cube c1;Cube c1(4, 5, 6);return 0;}
基类成员在派生类的重载
#include<bits/stdc++.h>using namespace std;/*** 基类成员在派生类的重载* */class Point {public:Point(int x, int y) {Point::x = x;Point::y = y;}float area() {return 0.0;}private:int x;int y;};class Circle: public Point {public:Circle(int x, int y, int r): Point(x, y) {Circle::radius = r;}float area() {return 3.1415926535*radius*radius;}private:int radius;};int main() {Point p(10, 10);Circle c(5, 5, 20);cout<<"point1:"<<p.area()<<endl;cout<<"circle1:"<<c.area()<<endl;cout<<"point1:"<<c.Point::area()<<endl; // 可以通过作用域符号找到基类的同名函数return 0;}
虚函数
#include<bits/stdc++.h>using namespace std;/*** 虚函数的作用* */class Undergra {public:virtual void cal_fee() {fee1 = 4200;fee2 = 800;fee3 = 400;fee = fee1 + fee2 + fee3;}virtual void dis() {cout<<"undergraduate fee:"<<endl;cout<<"study fee:"<<fee1<<endl;cout<<"sleep fee:"<<fee2<<endl;cout<<"other fee:"<<fee3<<endl;cout<<"total fee:"<<fee<<endl;}protected:int fee1;int fee2;int fee3;int fee;};class PostGra: public Undergra {public:void cal_fee() {fee1 = 1800;fee2 = 400;fee = fee1 + fee2;}void dis() {cout<<"postgraduate fee:"<<endl;cout<<"sleep fee:"<<fee1<<endl;cout<<"other fee:"<<fee2<<endl;cout<<"total fee:"<<fee<<endl;}};int main() {Undergra u1;PostGra p1;Undergra *ptr = &u1;ptr->cal_fee();ptr->dis();ptr = &p1;ptr->cal_fee();ptr->dis();return 0;}
虚函数是其他类的派生类,不会影响基类的同名函数
#include<bits/stdc++.h>using namespace std;/*** 虚函数* 如果基类成员函数是虚函数,那么所有派生类都是虚函数* 如果虚函数是其他类的派生类,那么基类的同名函数保持原有性质* */class A {public:void f(int i) {cout<<"A"<<endl;}};class B: public A {public:virtual void f(int i) {cout<<"B"<<endl;}};class C: public B {public:void f(int i) {cout<<"C"<<endl;}};class D: public C {public:void f(int ) {cout<<"D"<<endl;}};int main() {A *pa, a;B *pb, b;C c;D d;pa = &a; pa->f(1);pa = &b; pa->f(1);pa = &c; pa->f(1);pa = &d; pa->f(1);// 由于 A 的 f 不是虚函数,那么其子类都会调用 A 的f函数// B 的f是虚函数,那么其子类的f 都具有虚函数的性质pb = &b; pb->f(1);pb = &c; pb->f(1);pb = &d; pb->f(1);return 0;}
只有通过基类指针和引用才能实现虚函数特性
#include<bits/stdc++.h>using namespace std;/*** 只有通过基类指针和引用才能实现虚函数特性* */class B {public:virtual void f() {cout<<"B f"<<endl;}};class D: public B {public:void f() {cout<<"D f"<<endl;}};int main() {D d;B *pb = &d, &rb = d, b;b = d; // 截断赋值,因此实质还是调用B的函数b.f();pb->f(); // 虚函数特性rb.f(); // 虚函数特性return 0;}
派生类从基类继承的成员函数访问虚函数时,会访问派生类的版本
#include<bits/stdc++.h>using namespace std;/*** 派生类从基类继承的成员函数访问虚函数时,会访问派生类的版本* */class B {public:void f() {g();}virtual void g() {cout<<"B g"<<endl;}};class D: public B {public :void g() {cout<<"D g"<<endl;}};int main() {D d;d.f(); // 这里访问的是派生类中的g,如果 virtual 关键字去掉,那么访问基类中的greturn 0;}
虚函数调用过程
#include<bits/stdc++.h>using namespace std;/*** 虚函数调用过程* */class B {public:void f() {cout<<"B f"<<endl;}virtual void vf() {cout<<"B vf"<<endl;}void ff() {vf();f();}virtual void vff() {vf();f();}};class D: public B {public:void f() {cout<<"D f"<<endl;}void ff() {f();vf();}void vf() {cout<<"D vf"<<endl;}};int main() {D d;B *pb = &d;pb->f(); // 非虚函数,调用 B 的fpb->ff(); // 非虚函数,调用 B 的ff,从而调用 D的vf 以及B 的fpb->vf(); // 虚函数,调用 D 的vfpb->vff(); // 虚函数,调用 D 的vf 以及 B 的freturn 0;}
虚析构函数
#include<bits/stdc++.h>using namespace std;/*** 虚析构函数* */class A {public :virtual ~A() {cout<<"destruct A"<<endl;}};class B: public A {public:~B() {cout<<"destruct B"<<endl;}};int main() {A *p = new B();delete p;return 0;}
输出
destruct Bdestruct A
如果没有 virtual ,那么只会调用 A 的析构函数
纯虚函数
#include<bits/stdc++.h>using namespace std;/*** 纯虚函数* */class Point {public:Point(int i = 0, int j = 0) {x0 = i;y0 = j;}virtual void Draw() = 0;private:int x0, y0;};class Line: public Point {public:Line(int i = 0, int j = 0, int m = 0, int n = 0): Point(i, j) {x1 = m;y1 = n;}void Draw() {cout<<"draw line"<<endl;}private:int x1, y1;};class Ellipse: public Point {public:Ellipse(int i = 0, int j = 0, int p = 0, int q = 0): Point(i, j) {x2 = p;y2 = q;}void Draw() {cout<<"draw ellipse"<<endl;}private:int x2, y2;};int main() {Line *line = new Line;Ellipse *ellipse = new Ellipse;line->Draw();ellipse->Draw();delete line, ellipse;return 0;}
抽象类
#include<bits/stdc++.h>using namespace std;/*** 抽象类* */class Figure {public:virtual float area()=0;};class Circle: public Figure {public:Circle(float r) {radius = r;}float area() {return radius * radius * 3.1415926535;}private:float radius;};class Triangle: public Figure {public:Triangle(float h, float w) {high = h;width = w;}float area() {return high * width * 0.5;}protected:float high, width;};class Rectangle: public Triangle {public:Rectangle(float h, float w):Triangle(h, w) {}float area() {return high * width;}};int main() {Figure *p[6];p[0] = new Triangle(3.0, 2.0);p[1] = new Rectangle(2.5, 3.0);p[2] = new Rectangle(5.0, 1.0);p[3] = new Rectangle(3.0, 6.0);p[4] = new Circle(5.2);p[5] = new Circle(8.0);for(int i = 0; i < 6; i++) {printf("area[%d] = %f\n", i, p[i]->area());}return 0;}
抽象类不能建立对象
#include<bits/stdc++.h>using namespace std;/*** 抽象类不能建立对象* 函数原型不一样,仍然是抽象类* */class Figure {protected:double x, y;public:void set(double i, double j) {x = i;y = j;}virtual void area() = 0;};class Triangle : public Figure {public:void area() {printf("triangle area : %f\n", x*y*0.5);}};class Rectangle : public Figure {public:void area(int i) { // 只有函数原型一模一样才是虚函数,否则是重载,因此 Rectangle 仍然是抽象类printf("rectangle area : %f\n", x*y);}};int main() {Figure *pf;// Figure f; // 错误,抽象类不能建立对象// Rectangle r; // 错误,area 是重载而不是虚函数,因此仍然是抽象类Triangle t;t.set(10, 20);pf = &t;pf->area();Figure &rf = t;rf.set(20, 20);rf.area();return 0;}
