在类的定义中,前面有virtual关键字的成员函数就是虚函数。
class base{ virtual int get(); }; int base::get(){}
virtual关键字只用在类定义里的函数声明中,写函数体时不用。
多态一:
派生类的指针可以赋给基类指针,通过基类指针调用基类和派生类中的同名虚函数时:
- 若该指针指向一个基类的对象,那么被调用是基类的虚函数;
- 若该指针指向一个派生类的对象,那么被调用是派生类的虚函数
class CBase { public: virtual void SomeVirtualFunction(){} }; class CDerived :public CBase { public: virtual void SomeVirtualFunction(){} }; int main() { CDerived ODerived; CBase *p = &ODerived; p->SomeVirtualFunction(); return 0; }
多态二:
派生类的对象可以赋给基类引用,通过基类指针调用基类和派生类中的同名虚函数时:
- 若该引用引用的是一个基类的对象,那么被调用是基类的虚函数;
- 若该引用引用的是一个派生类的对象,那么被调用是派生类的虚函数
class CBase { public: virtual void SomeVirtualFunction(){} }; class CDerived :public CBase { public: virtual void SomeVirtualFunction(){} }; int main() { CDerived ODerived; CBase &r = ODerived; r.SomeVirtualFunction(); return 0; }
多态例一:
#include <iostream> #include <stdlib.h> #include <math.h> using namespace std; class CShape { public: virtual double Area() = 0; //纯虚函数 virtual void PrintInfo() = 0; }; class CRectangle :public CShape { public: int w, h; virtual double Area(); virtual void PrintInfo(); }; double CRectangle::Area() { return w*h; } void CRectangle::PrintInfo() { cout << "Rectangle:" << Area() << endl; } class CCircle :public CShape { public: int r; virtual double Area(); virtual void PrintInfo(); }; double CCircle::Area() { return 3.14*r*r; } void CCircle::PrintInfo() { cout << "Circle:" << Area() << endl; } class CTriangle :public CShape { public: int a,b,c; virtual double Area(); virtual void PrintInfo(); }; double CTriangle::Area() { double p = (a + b + c) / 2.0; return sqrt(p * (p - a)*(p - b)*(p - c)); } void CTriangle::PrintInfo() { cout << "Triangle:" << Area() << endl; }
CShape *pShapes[100]; int MyCompare(const void *s1, const void *s2);
int main() { int i; int n; CRectangle *pr; CCircle *pc; CTriangle *pt; cin >> n; for (i = 0; i < n; i++) { char c; cin >> c; switch (c) { case'R': pr = new CRectangle(); cin >> pr->w >> pr->h; pShapes[i] = pr; break; case'C': pc = new CCircle(); cin >> pc->r; pShapes[i] = pc; break; case 'T': pt = new CTriangle(); cin >> pt->a >> pt->b >> pt->c; pShapes[i] = pt; break; } } qsort(pShapes, n, sizeof(CShape*), MyCompare); for (i = 0; i < n; i++) pShapes[i]->PrintInfo(); return 0; } int MyCompare(const void * s1, const void * s2) { double a1, a2; CShape * * p1; // s1,s2 是 void * ,不可写 “* s1”来取得s1指向的内容 CShape * * p2; p1 = (CShape * *)s1; //s1,s2指向pShapes数组中的元素,数组元素的类型是CShape * p2 = (CShape * *)s2; // 故 p1,p2都是指向指针的指针,类型为 CShape ** a1 = (*p1)->Area(); // * p1 的类型是 Cshape * ,是基类指针,故此句为多态 a2 = (*p2)->Area(); if (a1 < a2) return -1; else if (a2 < a1) return 1; else return 0; }
多态实现的原理:
每一个有虚函数的类(或有虚函数的类的派生类)都有一个虚函数表,该类的任何对象中都放着虚函数表的指针。虚函数表中列出了该类的虚函数地址。多出来的4个字节就是用来放虚函数表的地址的。
纯虚函数:没有函数体的虚函数
class A{ private: int a; public: virtual void Print()=0; void fun(){cout<<"fun";} };
抽象类:包括纯虚函数的类
- 只能作为基类来派生新类使用
- 不能创建抽象类的对象
- 抽象类的指针和引用
class A { public: virtual void f() = 0; //纯虚函数 void g( ) { this->f( ); } //ok A( ){ } //f( ); // 错误 }; class B : public A{ public: void f(){ cout<<"B: f()"<<endl; } }; int main(){ B b; b.g(); return 0; }
抽象类中,
- 在成员函数内可以调用纯虚函数
- 在构造函数/析构函数内部不能调用纯虚函数
如果一个类从抽象类派生而来,它实现了基类中的所以纯虚函数,才能成为非抽象类。
No comments:
Post a Comment