您的位置:首页 > 职场人生

虚函数,虚析构函数,纯虚函数,抽象类。

2008-10-04 10:25 495 查看
虚函数,虚析构函数,纯虚函数,抽象类。
author: ZJ 07-12-31
Blog: http://zhangjunhd.blog.51cto.com/
1.虚函数
1.1虚函数的作用
虚函数的作用是允许在派生类中重新定义与基类同名的函数,并且可以通过基类指针或引用来访问基类和派生类中的同名函数。
[align=left]class Time{[/align]
[align=left] public:[/align]
[align=left] Time(int=0,int=0,int=0); [/align]
[align=left] void show();[/align]
[align=left] protected:[/align]
[align=left] int hour;[/align]
[align=left] int min;[/align]
[align=left] int sec;[/align]
[align=left]};[/align]
[align=left] [/align]
[align=left]class LocalTime:public Time{[/align]
[align=left] public:[/align]
[align=left] LocalTime(int=0,int=0,int=0,string="+8");[/align]
[align=left] void show();[/align]
[align=left] protected:[/align]
[align=left] string zone;[/align]
[align=left]};[/align]
[align=left] [/align]
[align=left]Time::Time(int h,int m,int s):hour(h),min(m),sec(s){}[/align]
[align=left] [/align]
[align=left]void Time::show(){[/align]
[align=left] cout<<hour<<":"<<min<<":"<<sec<<endl;[/align]
[align=left]}[/align]
[align=left] [/align]
[align=left]LocalTime::LocalTime(int h,int m,int s,string z):Time(h,m,s),zone(z){}[/align]
[align=left] [/align]
[align=left]void LocalTime::show(){[/align]
[align=left] cout<<hour<<":"<<min<<":"<<sec<<"@"<<zone<<endl; [/align]
[align=left]}[/align]
[align=left] [/align]
[align=left]int main(){[/align]
[align=left] Time t;[/align]
[align=left] LocalTime lt;[/align]
[align=left] Time *pt=&t;[/align]
[align=left] pt->show();[/align]
[align=left] pt=<[/align]
[align=left] pt->show(); [/align]
[align=left] system("PAUSE");[/align]
[align=left] return EXIT_SUCCESS; [/align]
}
结果:
0:0:0
0:0:0
这里通过指针找到派生类,但无法调用派生类show()。如果使用虚函数。
将基类Time中的show()函数声明为虚函数, 其余不变。
[align=left]class Time{[/align]
[align=left] public:[/align]
[align=left] Time(int=0,int=0,int=0); [/align]
[align=left] virtual void show();[/align]
[align=left]…[/align]
};
结果:
0:0:0
0:0:0@+8
本来,基类指针是指向基类对象的,如果用它指向派生类对象,则进行指针类型转换,将派生类对象的指针先转换为基类指针,所以基类指针指向的是派生类对象中的基类部分。在程序修改前,是无法通过基类指针去调用派生类对象中的成员函数的。
虚函数突破这一限制,在派生类的基类部分中,派生类的虚函数取代了基类原来的虚函数,因此在使用基类指针指向派生类对象后,调用虚函数时就调用了派生类的虚函数。

1.2虚函数的使用方法
【1】在基类用virtual声明成员函数为虚函数。这样就可以在派生类中重新定义此函数,为它赋予新的功能,并能方便地被调用。

【2】在派生类中重新定义此函数,要求函数名、函数(返回)类型、函数参数个数和类型与基函数的虚函数相同。如果在派生类中没有对基类的虚函数重定义,则派生类简单地继承直接基类的虚函数。
有一种情况例外,在这种情况下派生类与基类的成员函数返回类型不同,但仍起到虚函数的作用。即基类虚函数返回一个基类指针或基类引用,而子类的虚函数返回一个子类的指针或子类的引用。
[align=left]class Base{[/align]
[align=left] public:[/align]
[align=left] virtual Base *fun(){[/align]
[align=left] cout<<"Base's fun()."<<endl;[/align]
[align=left] return this;[/align]
[align=left] } [/align]
[align=left]};[/align]
[align=left] [/align]
[align=left]class Derived:public Base{[/align]
[align=left] public:[/align]
[align=left] virtual Derived *fun(){[/align]
[align=left] cout<<"Derived's fun()."<<endl;[/align]
[align=left] return this; [/align]
[align=left] }[/align]
[align=left]};[/align]
[align=left] [/align]
[align=left]void test(Base &x){[/align]
[align=left] Base *b;[/align]
[align=left] b=x.fun();[/align]
[align=left]}[/align]
[align=left] [/align]
[align=left]int main(){[/align]
[align=left] Base b; [/align]
[align=left] Derived d;[/align]
[align=left] test(b);[/align]
[align=left] test(d); [/align]
[align=left] system("PAUSE");[/align]
[align=left] return EXIT_SUCCESS; [/align]
}
结果:
Base's fun().
Derived's fun().

【3】C++规定,当一个成员函数被声明为虚函数后,其派生类中的同名函数(符合2中定义的函数)都自动成为虚函数。

【4】定义一个指向基类对象的指针变量,并使其指向同一类族中的某个对象。通过该指针变量调用此函数,此时调用的就是指针变量指向的对象的同名函数。

1.3声明虚函数的限制
【1】只能用virtual声明类的成员函数,使它成为虚函数,而不能将类外的普通函数声明为虚函数。

【2】一个成员函数被声明为虚函数后,在同一类族中的类就不能再定义一个非virtual的但与该虚函数具有相同参数(个数与类型)和函数返回值类型的同名函数。

【3】静态成员函数不能是虚函数,因为静态成员函数不受限于某个对象。

【4】inline函数不能是虚函数,因为inline函数是不能在运行中动态确定其位置的。即使虚函数在类的内部定义,编译时,仍将其视为非inline的。

【5】使用虚函数,系统要有一定的空间开销。当一个类带有虚函数时,编译器会为该类构造一个虚函数表(virtual function tanle,vtable),它是一个指针数组,存放每个虚函数的入口地址。
2.虚析构函数
[align=left]class Time{[/align]
[align=left] public:[/align]
[align=left] Time(int=0,int=0,int=0); [/align]
[align=left] ~Time(){[/align]
[align=left] cout<<"Time destructor"<<endl;[/align]
[align=left] } [/align]
[align=left] protected:[/align]
[align=left] int hour;[/align]
[align=left] int min;[/align]
[align=left] int sec;[/align]
[align=left]}; [/align]
[align=left] [/align]
[align=left]class LocalTime:public Time{[/align]
[align=left] public:[/align]
[align=left] LocalTime(int=0,int=0,int=0,string="+8");[/align]
[align=left] ~LocalTime(){[/align]
[align=left] cout<<"LocalTime destructor"<<endl;[/align]
[align=left] }[/align]
[align=left] protected:[/align]
[align=left] string zone;[/align]
[align=left]}; [/align]
[align=left] [/align]
[align=left]Time::Time(int h,int m,int s):hour(h),min(m),sec(s){}[/align]
[align=left] [/align]
[align=left]LocalTime::LocalTime(int h,int m,int s,string z):Time(h,m,s),zone(z){}[/align]
[align=left] [/align]
[align=left]int main(){[/align]
[align=left] Time *p=new LocalTime;//指向派生类[/align]
[align=left] delete p; [/align]
[align=left] system("PAUSE");[/align]
[align=left] return EXIT_SUCCESS; [/align]
}
结果:
Time destructor
从结果可以看出,执行的还是基类的析构函数,而程序的本意是希望执行派生类的析构函数。此时将基类的析构函数声明为虚析构函数,
[align=left]virtual ~Time(){[/align]
[align=left] cout<<"Time destructor"<<endl;[/align]
}
结果:
LocalTime destructor
Time destructor
如果将基类的析构函数声明为虚函数,由该基类所派生的所有派生类的析构函数也自动成为虚函数。
把基类的析构函数声明为虚函数的好处是,如果程序中delete一个对象,而delete运算符的操作对象是指向派生类对象的基类指针,则系统会调用相应类的析构函数。
构造函数不能声明为虚函数。
3.纯虚函数
virtual void show()=0;//纯虚函数
这里将show()声明为纯虚函数(pure virtual function)。纯虚函数是在声明虚函数时被“初始化”为0的虚函数。
声明纯虚函数的一般形式为,
virtual 函数类型 函数名(参数列表)=0;
纯虚函数没有函数体;最后的“=0”并不代表函数返回值为0,它只起形式上的作用,告诉编译器“这是纯虚函数”;这个一个声明语句,最后有分号。
声明纯虚函数是告诉编译器,“在这里声明了一个虚函数,留待派生类中定义”。在派生类中对此函数提供了定义后,它才能具备函数的功能,可以被调用。
纯虚函数的作用是在基类中为其派生类保留了一个函数的名字,以便派生类根据需要对它进行定义。
如果在一个类中声明了纯虚函数,而在其派生类中没有对该函数定义,则该函数在派生类中仍为纯虚函数。
4.抽象类
将不用来定义对象而只作为一种基本类型用作继承的类,称为抽象类(abstract class),由于它常用作基类,通常称为抽象基类。凡是包含纯虚函数的类都是抽象类。
如果在派生类中没有对所有的纯虚函数进行定义,则此派生类仍然是抽象类,不能用来定义对象。
可以定义指向抽象类数据的指针变量。当派生类成为具体类后,就可以用这个指针指向派生类对象,然后通过该指针调用虚函数。
本文出自 “子 孑” 博客,请务必保留此出处http://zhangjunhd.blog.51cto.com/113473/57543本文出自 51CTO.COM技术博客
[align=center]上一篇 就地移动栈数据  下一篇 C++:类型数据间的转换 [/align]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  函数 职场 休闲
相关文章推荐