当在基类中无法为虚函数提供任何有实际意义的定义时,可以将该虚函数声明为纯虚函数,它的实现留给该基类的派生类去做。
纯虚函数的声明和定义:
★纯虚函数是一种特殊的虚函数,其格式一般如下:
class 类名
{
virtual 类型 函数名 (参数表)=0;
…
};
|
★纯虚函数不能被直接调用,仅提供一个与派生类一致的接口。
抽象类:
★一个类可以包含多个纯虚函数。只要类中含有一个纯虚函数,该类便为抽象类。一个抽象类只能作为基类来派生新类,不能创建抽象类的对象,如中的A类便是抽象类,创建A类的对象是非法的,如:A a; //错误:A为抽象类
★但可声明一个指向抽象类的指针,如:A* a = NULL; A* a = new B;
★应注意:“A* a=new A;”非法,因为该语句试图创建A的对象。
★和普通的虚函数不同,在派生类中一般要对基类中纯虚函数进行重定义,或者在派生类中再次将该虚函数声明为纯虚函数。这说明,抽象类的派生类也可以是抽象类,只有在派生类中给出了基类中所有纯虚函数的实现时,该派生类便不再是抽象类。和纯虚函数一样,抽象类只起到提供统一接口的作用。
#include <iostream>
#include <math.h>
using namespace std;
const float PI = 3.1415;
class Figure
{
public:
virtual float area()=0;
virtual void display()=0;
};
class Circle : public Figure
{
public:
Circle(float radius):_radius(radius){}
float area()
{ return PI*_radius*_radius; }
void display()
{ cout<<"圆:"; }
private:
float _radius;
};
|
class Rectangle : public Figure
{
public:
Rectangle(float x,float y):_x(x),_y(y){}
float area()
{ return _x*_y; }
void display()
{ cout<<"矩形 :"; }
private:
float _x;
float _y;
};
class Triangle : public Figure
{
public:
Triangle(float a,float b,float c):_a(a),_b(b),_c(c){}
float area()
{
float p=(_a+_b+_c)/2;
return sqrt(p*(p-_a)*(p-_b)*(p-_c));
}
void display()
{ cout<<"三角形:"; }
private:
float _a;
float _b;
float _c;
};
|
void test(Figure * fig)
{
fig->display();
cout<<fig->area()<<endl;
}
int main()
{
Circle circle(10);
Rectangle rectangle(5,6);
Triangle triangle(3,4,5);
test(&circle);
test(&rectangle);
test(&triangle);
return 0;
}
|
#include <iostream>
using namespace std;
class A
{//抽象类,不能实例化对象
public:
virtual void display()=0; //纯虚函数
};
class B : public A
{//对于派生类而言,如果没有完成基类的纯虚函数的实现,则该派生类也会变成抽象类
public:
virtual void display()
{ cout<<"B::display()"<<endl; }
};
class C : public B
{
public:
virtual void display()
{ cout<<"C::display()"<<endl; }
};
void test(A * pa)
{ pa->display(); }
int main()
{
B b;
A * pa = &b;
test(pa);
C c;
pa = &c;
test(pa);
return 0;
}
|
//只定义protected类型构造函数的类也是抽象类
#include <iostream>
using namespace std;
class Base
{//抽象类
public:
void disp()
{ cout<<"x = "<<_x<<endl; }
protected:
Base(int x=0):_x(x){} //构造函数声明protected
private:
int _x;
};
class Child:public Base
{
public:
//Base b; //error,在派生类不能创建Base类对象,和在main函数建立对象一样
Child(int x1):Base(x1){}; //派生类中可调用protected构造函数
};
int main()
{
//Base b; //error,不能在类外创建Base类对象
Child c(1);
c.disp();
return 0;
}
|
只定义了protected型构造函数的类也是抽象类
★对一个类来说,如果只定义了protected型的构造函数而没有提供public构造函数,无论是在外部还是在派生类中作为其对象成员都不能创建该类的对象,但可以由其派生出新的类,这种能派生新类,却不能创建自己对象的类是另一种形式的抽象类。
使用static成员函数为包含private构造函数的类创建对象
★前面讲了构造函数可以为public型、也可以为protected型。其实,构造函数也可以是private型的。
★此时,不能直接在外部函数和派生类中使用“类名+对象名”的形式来创建该类对象,但可以通过类的static函数成员来创建类的实例。
★与此类似,也可以使用static成员函数为包含protected型构造函数的类创建对象
#include<iostream>
using namespace std;
class A
{
public:
static A* createObject(int x)
{
return new A(x);
}
~A() // 静态对象没有this指针
{
cout<<"~A()"<<endl;
}
static void deleteObject(A* p)
{ // 所以要这样来析构
if(NULL!=p)
{
delete p;
p = NULL;
}
}
void disp()
{
cout<<"x = "<<_x<<endl;
}
private:
int _x;
A(int x=0):_x(x){}
};
|
int main()
{
//A a; //错误, Example的构造函数是private类型, 不能访问
//A* a = new A(1); //错误, Example的构造函数是private类型, 不能new
A* a = A::createObject(1);
a->disp();
A::deleteObject(a);
return 0;
}
|