在类的定义中,前面有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