要素类和对象模版类的继承教案资料_第1页
要素类和对象模版类的继承教案资料_第2页
要素类和对象模版类的继承教案资料_第3页
要素类和对象模版类的继承教案资料_第4页
要素类和对象模版类的继承教案资料_第5页
已阅读5页,还剩154页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

C++要素类和对象模版类的继承预备知识——C++、类与对象C复习数据类型:在C语言中:基本类型和构造类型基本类型:整型、浮点型、字符型、双精度型

构造类型:数组、结构、联合、指针、枚举型数据对象:intn=3;inta[3];a[0]=-1;//整型数据对象charch=‘A’;//字符类型数据对象对象指针:int*p=&n,*q=a;C复习标识符表达式语句:赋值句、条件句、循环句、函数调用(输入输出)函数:返回值类型,函数名,参数列表递归:直接递归、间接递归C++介绍一.C++要素(BorlandC,VC)/*………*/

段注释以/*开始到*/结束

//行注释到行末

2.注释

例1:constintm=10;//定义m为常量值是104.

常量说明const例2:constinta[]={1,3,5,7,9};//定义a是常量数组例3.int*constp;//常指针p指向一个固定的地址

例4.constint*q;//指针q指向常量可以在任何地方申明一个变量

例for(inti=0;i<5;i++)其作用域从申明地起到文末或函数末5.变量申明但不能while(inti)i++;intf(inta,intb=0);

调用f(5),即调用f(5,0);

6.函数缺省值参数缺省参数要写在参数表的右边intf(inta,intb=0,intc=1);

inlineintsquare(intx){returnx*x;}

内联函数先编译,效率高,速度快但只能有四五个语句,不能有循环语句,条件语句.7.内联函数

overloadabs;

intabs(int);

floatabs(float);

同名不同参数的函数可以重载系统会自动选择调用8.函数重载定义函数的变量参数

intf(int&x){intn=2*x++;returnn;}x为函数f的变量参数

调用实参的地址调用后实参的值可以改变函数需要两个以上返回值时,用变量参数9.引用操作符&例

int*p,*q;

p=newint(3);

q=newint[4];

为p分配一个整形地址(2字节)*p==3为q分配4个整形地址(8个连续字节)

deletep;//撤销p的地址

delete[]q;//撤销q的多个连续地址

10.动态函数动态变量

newdelete#include“iostream.h”

inta,b;charx,y;

cout<<“Enterx,y,a,b”<<endl;

cin>>x>>y;\\从键盘为变量x,y输入数据

cin>>a>>b;\\从键盘为变量a,b输入数据

cout<<“x=”<<x<<endl;

cout<<y<<a<<b<<endl;11.输入输出文件输入输出include“fstream.h”include“stdlib.h”voidmain(){ifstreaminfile(“datafile1.doc”);

if(!infile){cerr<<“Cannotopendatafile1.doc”<<endl;exit(1);}ofstreamoutfile(“datafile2.doc”);

if(!outfile){cerr<<“Cannotopendatafile2.doc”<<endl;exit(1);}

intn;stringname;while(infile>>n){infile>>name;outfile<<n<<“”<<name<<endl;}}一.C++要素(BorlandC3.1)1.文件扩展名*.cpp2.注释/*………*/段注释

//行注释到行末3.续行\常量说明const5.变量申明可以在任何地方申明一个变量6.函数缺省值参数

int

f(inta,intb=0);7.内联函数8.重载overload引用操作符&10.动态函数动态变量newDelete11输入输出

二.

类和对象

1.类的定义

class类名称{private:数据成员;成员函数;protected:数据成员;成员函数;public:数据成员; 成员函数;};//类定义结束必须有分号“;”class

是保留字,

作用与struct

相同

定义一个结构也叫类。

private(私有),缺省

protected(保护)

,

public(公有)都是访问限制例计数器类

存储于文件“count.h”中

classcounter{private://私有成员

unsignedintvalue;//数据成员

public://公有成员counter(){value=0;}//无参构造函数counter(intx){if(x>0)value=x;elsevalue=0;}//有参构造函数

voidincrement(){if(value<65535)value++;}

voiddecrement(){if(value>0)value--;}

unsignedaccess_value(){returnvalue;}};counterc1,c2;//语句1

counterc3(5);//语句2语句1定义counter类的对象c1,c2,即实际变量(实例)。对象定义时必须为数据成员赋初值即初始化。初始化由类中的构造函数自动完成。语句1自动调用counter类中无参构造函数,使c1.value=c2.value=0。

语句2定义对象c3,自动调用有参构造函数使c3.value=5.2.对象的定义object注意:不能使用c1.value为它赋值;因为value在counter类中是私有成员不可见,只能用成员函数来调用。对象不能直接调用私有成员,只能通过公有成员函数来调用私有成员对象调用成员函数,叫发一个消息为c1发消息:c1.increment();//计数器自动加1c1.decrement();//计数器自动减1例计数器测试程序#include“iostream.h”

#include“count.h”voidmain(){counterc1,c2;

for(inti=1;i<=8;i++){c1.increment();cout<<“\nc1=”<<c1.access_value();c2.increment();}cout<<“c2=”<<c2.access_value();

for(i=1;i<=5;i++){c2.decrement();cout<<“\nc2=”<<c2.access_value();c1.decrement();}cout<<“c1=”<<c1.access_value();}测试结果c1=1c1=2c1=3c1=4c1=5c1=6c1=7c1=8c2=8c2=7c2=6c2=5c2=4c2=3c1=3圆的类classCircle{floatradius;

public:Circle(floatr=0):radius(r){}//构造函数floatGetRadius();floatCircleCircum();floatCircleArea();};成员函数类外定义Circle::Circle(floatr)//构造函数{radius=r;}floatCircle::GetRadius(){returnradius;}floatCircle::CircleCircum(){return2*3.14.6*radius;}floatCircle::CircleArea(){return3.1416*radius*radius;}圆类的测试#include“iostream.h”

#include“circle.h”voidmain(){Circlea(3),b(2);cout<<“CircumofCirclea=”<<a.CircleCircum()<<endl;cout<<“AreaofCircleb=”<<b.CircleArea()<<endl;}长方形类classRectangle{floatx,y;public:Rectangle(floata=0,floatb=0):x(a),y(b){}floatRecCircum(){return2*(x+y);}floatRecArea(){returnx*y;}};a.对象指针如同定义一个对象一样,用类名可以申明一个对象指针。例counter*p,*q;申明counter类的指针,指针没有初始化,调用指针必须先分配内存,或指向一个变量的地址,否则出严重错误,甚至死机。3.对象指针和对象数组

(1)p=newcounter(3);分配一个整形数据内存,这时系统自动调用有参构造函数初始化*p的value=3;(2)q=newcounter[3];分配三个连续整形数据内存,这时系统自动调用无参构造函数初始化q,q+1,q+2的value都是0。如果类中没有无参构造函数,语句(2)出错。

确定地址后的对象指针可以调用类中公有数据及公有函数。p→increment();(q+1)→decrement();(*p).decrement();

(*p).decrement()中的括号不能省略,因为运算符.的优先级高于*;

对象指针用毕,要予以撤销,释放内存,deletep;delete[]q;

撤销后的指针可以再用,只要重新分配内存或指向一个内存。b.对象数组

如果类中有无参构造函数,可以定义对象数组(3)counterc[3];这时系统自动调用无参构造函数初始化c[0],c[1],c[2]的value都是0。如果类中没有无参构造函数,语句(3)出错。a.一个类中的数据成员不可以初始化,例classA{intvalue=0;\\出错.......};b.另一个类的对象可以做本类的数据成员,但要先定义后作成员。只先申明不行。本类对象不可以做自己的数据成员。c.指向本类或另一类对象的指针,或引用可以作本类的数据成员。只要先申明就可以。4.类的数据成员d.公有成员和私有成员的先后次序可以交换。可以把私有成员写在类的前部,也可以写在后部。e.本类对象可以调用本类公有数据或公有函数,不能调用私有数据和私有成员。例classA;classB

{A*p;//合法A&q;//合法B*r;//合法Aa;//出错Bb;//出错

};长方形和圆的类classRecCircle{RectangleRec;

CircleCir;public:

RecCircle(floata,floatb,floatc):Rec(a,b),Cir(c){}floatCircum(){returnRec.RecCircum()+Cir.CircleCircum();}floatArea(){returnRec.RecArea()+Cir.CircleArea();};成员函数也叫类所具有的方法或操作。函数头叫方法的界面,也叫消息模式。函数可以重载(要求参数不同)不必用overload。可以类内申明类外定义,类内定义时不用inline即内联。成员函数可以调用本类数据成员,无论公有或私有。对象调用公有成员函数叫做发一个消息。5.类的成员函数构造函数可以重载,带缺省参数时,要特别注意避免二义性。

构造函数一般都是公有函数。只有私有构造函数的类不能定义对象。只有本类对象或本类成员函数才能调用成员函数。

成员函数必须由对象调用,调用成员函数的对象可以看作一个隐含的参数,这是一个指针参数,用this表示。this指针指向调用成员函数的对象。例Circle::CircleArea(){return3.1416*radius*radius;}//其中radius实际意义是this→radius.Circlea(3.4);cout<<a.CircleArea();//this指针指向a6.This指针

this指针counter::increament(){if(value<65535)value++;}//隐含参数this指针,this->value

counterc;c.increament();//实际参数是c,this指向c

与类名同名的成员函数叫构造函数,构造函数没有返回类型。构造函数的作用是自动为对象初始化。对象不能调用构造函数。如果一个类中没有构造函数,系统会自动生成一个无参构造函数。如果一个类中有有参构造函数,系统就不再自动生成无参构造函数,这时,用类定义对象数组或对象指针都可能出错。7.构造函数一个类中如果没有构造函数,系统会自动生成

一个无参构造函数,使所有的数据成员都置0。

一个类中如果有有参构造函数,系统就不再生

成无参构造函数。例如RecCirle类中,就没有无参构造函数。

这时要小心,下面一个语句会出错

RecCircled;//出错无法初始化

RecCircles[3];//出错无法初始化正确的定义形式是

RecCircled(2.0,3.5,4);8.拷贝构造函数构造函数的参数不能是本类对象,但可以是本类对象的引用,这样的构造函数叫拷贝构造函数。classCircle{floatradius;

public:Circle(floatr=0):radius(r){}//构造函数Circle(Circle&c){radius=c.radius;}//拷贝构造函数floatGetRadius();floatCircleCircum();floatCircleArea();};

1)用已有对象定义新的对象。Circlea(2);Circleb(a);

第二个语句就是利用拷贝构造函数定义赋数对象b,b的半径等于a的半径。

拷贝构造函数的作用:拷贝构造函数的作用:2)本类对象作函数的参数时,要用拷贝构造函数传值。3)一个函数的返回值是本类对象时,要用拷贝构造函数赋值。CircleFun(Circlet){returnCircl(2*t.radius);}如果类中没有拷贝构造函数系统会自动生成一个。如果类中有指针成员,就必须专门定义拷贝构造函数,否则可能出错。例classA

{int*p;pubic:A(){p=newint(0);}A(A&s){p=newint(*s.p);};

以~开头与类名同名的成员函数称为析构函数。析构函数无参无返回值。例classA

{....

~A();....};9.析构函数析构函数的作用:当本类的一个对象用完后,系统自动调用析构函数,撤销内存。这种情况常在一个函数中发生,一个对象在函数中作局部变元,函数用毕后,局部变元失效,析构函数就会自动起作用。类中没有析构函数时系统会自动生成一个析构函数。当类中含有指针对象时,应当定义一个析构函数,以免指针指向的内存挂起失。classA{int*p;public:A(){p=newint;}....~A(){deletep;}....};注意类外对象指针用new分配的内存,不会调用析构函数,而要用delete释放。例坐标点point类classPoint{public:Point(int,int);//构造函数Point(Point&);//拷贝构造函数//~Point();析构函数

intget_x();//取横坐标

intget_y();//取纵坐标Pointoperator+(Point&);//重载+Pointoperator*(int);//重载*Pointoperator-();//一元函数-重载

Point&operator=(constPoint&);//赋值函数

private://私有数据

intx,y;friendistream&

operator>>(istream&,Point&);

//友元输入函数重载>>friendostream&

operator<<(ostream&,Point&);//友元输出函数重载<<

};Point::Point(inta,intb){x=a;y=b;}Point::Point(Point&p){x=p.get_x();y=p.get_y();}intPoint::get_x(){returnx;}intPoint::get_y(){returny;}PointPoint::operator+(Point&p){x=x+p.x;y=y+p.y;return*this;}PointPoint::operator*(intn){x=n*x;y=n*y;return*this;}Point

Point::operator-(){x=-x;y=-y;return*this;}Point&

Point::operator=(constPoint&p){x=p.x;y=p.y;return*this;}istream&

operator>>(istream&istr,Point&p){istr>>p.x>>p.y;returnistr;}ostream&

operator<<(ostream&ostr,Point&p){ostr<<“(”<<p.x<<“,”<<p.y<<“)”<<endl;

returnostr;}除了少数几个操作符,如“,”,“::”,“?:”,“{}”之外,其余都可以重载。二元运算在成员函数看来,只有一个参数,另一个是this指针。例PointPoint::operator+(Point&c);二元运算+在复数类中重载,变成只有一个参数。11.运算符(操作符)重载

Point

a1(1,2),a2(2,-1);a1=a1+a2;表达式a1=a1+a2中对象a1调用运算+,实际参数为a2,返回值还是Point类型,还可以再调用运算符+,因此表达式a1+a2+a1有意义。

在classPoint

中重载赋值函数

classPoint

{....

Point&operator=(constPoint&c){x=c.x;y=c.y;return*this;}......};12.赋值函数重载

赋值函数的作用是把一个对象的所有内容,赋予另一个对象.

c1=c2;c1=c1+c2;类中没有赋值函数时系统会自动生成一个赋值函数。当类中含有指针对象时,应当定义一个赋值函数,以保证值把内容赋值,而不是把地址赋值造成析构函数调用时出错。例classA

{int*p;public:

.....A&operator=(A&a)

{if(this=&a)return*this;else*p=*a.p;return*this;}.....};

一元运算作成员函数重载时变成零元函数。PointPoint::operator-(){x=-x;y=-y;returnreturn*this;}调用写成-c1或c1=-c2;13.一元运算重载10.友元友元有权访问类内所有成员,不论公有,保护,还是私有成员。友元没有this指针,必要时可以用类对象的引用作参数。友元可以是一个类,这时友元类中所有成员函数都是友元。友元不传递,不对称,不继承。友元没有this指针,比成员函数多一个参数。istream&

operator>>(istream&istr,Point&p){istr>>p.x>>p.y;returnistr;}ostream&

operator<<(ostream&ostr,Point&p){ostr<<“(”<<p.x<<“,”<<p.y<<“)”<<endl;

returnostr;}友元不是类的成员,不用类名域Point::operator函数在类内申明类外定义

例日期类保存于“date.h”中

classdate{intmonth,day,year;//私有数据

public:date(int,int,int);//有参构造函数

voidnext();

voidprint();}today;

inlinedate::date(inta,intb,intc){month=a;day=b;year=c;}voiddate::print(){cout<<month<<“/”<<day;cout<<“/”<<year<<endl;}voiddate::next(){switchmonth

case1:case3:case

5:case

7:case

8:case10:{if(day<31)day++;

else{month++;day=1;}}break;

case4:case6:case

9:case

11:{if(day<30)day++;

else{month++;day=1;}}break;

case

12:{if(day<31)day++;

else{year++;month=1;day=1;}}break;

case

2:case2:if((year%4==0)&&year%400!=0)

||(year%400==0)){if(day<29)day++;

else{month++;day=1;}}

else{if(day<28)day++;

else{month++;day=1;}}}例date类测试程序

#include“iostream.h”

#include“date.h”

void

main(){datetoday(2,13,2001);//定义对象datemyBirthday(6,24,1983);//定义对象today.next();//对象调用操作today.print();myBirthday.print();}测试结果2/14/20016/24/1983三、模版(template)

通用数据类

模版函数通用函数2.

类模版通用数据类型模版函数

通用函数

几个形式上完全相同的函数,只有

参数类型和返回值类型不同,可以写成通用函数,也叫模版函数。例.intmax(inta,intb)

{returna>b?a:b;}float

max(floata,floatb){returna>b?a:b;}

char

max(chara,charb){returna>b?a:b;}可以统一写成一个模版函数template<classT>Tmax(Ta,Tb){returna>b?a:b;}这里T是类型参数可以用任意一个标识符模版函数的调用对不同的参数都可以调用函数maxinta,b;charx,y;a=3;b=5;x='A';y='b';a=max(a,b);\\有意义x=max(x,y);\\有意义参数可以用字符串,甚至复杂的结构变量,对象,只要事先定义大小关系。2.类模版通用数据类型//array.h例.通用数组抽象数组类型

template<classT>

classArray{T*alist;//指针数据表示一个数组

intsize;//表示数组长度

public:

Array(ints=50)//构造函数

Array(constArray<T>&X);//拷贝构造函数~Array(){delete[]element;}//析构函数

Array<T>&operator=(constArray<T>&X);//赋值函数重载

T&operator[](inti);//一元运算[]重载下标函数

operatorT*()const;

//强制类型转换,将当前

//对象变成指向它的首地址的指针,

intArraySize()const;//取数组长

voidResize(intsz);//数组长重定义

friendostream&operator<<(ostream&,constArray<T>&);

//输出操作重载};template<classT>

classArray{T*alist;//指针数据表示一个数组

intsize;//表示数组长度

public:

Array(ints=50)//构造函数

Array(constArray<T>&X);//拷贝构造函数~Array(){delete[]element;}//析构函数Array<T>&operator=(constArray<T>&X);

//赋值函数重载

T&operator[](inti);//一元运算[]重载//下标函数

operatorT*()const;

//强制类型转换,将当前//对象变成指向它的首地址的指针,

intArraySize()const;//取数组长

voidResize(intsz);//数组长重定义

friendostream&operator<<

(ostream&,constArray<T>&);//输出操作重载};//构造函数

template<classT>Array<T>::Array(intsz){size=sz;alist=new

T[size];

if(alist==0){cout<<“内存不够”;

return;}}//析构函数destructortemplate<class

T>Array<T>::~Array(void){

delete[]alist;}//copyconstructor拷贝构造函数template<class

T>Array<T>::Array(constArray<T>&X){intn=X.size;//取对象X的长度作为当前对象的长size=n;alist=newT[n];//allocatedynamicarray

if(alist==0)//作正确性检查{cout<<“内存不够”;return;}

//copyarrayitemsfromXtocurrentobject

T*srcptr=X.alist;//addressatstartofX.alist

T*destptr=alist;//addressatstartofalist

while(n--)//copylist*destptr++=*srcptr++;}template<classT>//赋值函数重载Array<T>&Array<T>::operator=(constArray<T>&X){

intn=X.size;//取X的长度

if(size!=n)//若长度不同,重新分配内存

{delete[]alist;//destroyoriginalmemoryalist=newT[n];//allocateanewarrayif(alist==0){cout<<“内存不够”;return;}size=n;}

//将对象X的元素逐个拷贝到当前对象//copyarrayitemsfromXtocurrentobject

T*destptr=alist;

T*srcptr=X.alist;

while(n--)*destptr++=*srcptr++;//返回当前对象的值//returnreferencetothecurrentobject

return*this;}//一元运算[]重载下标函数

//overloadedindexoperator

template<classT>T&Array<T>::operator[](intn){

//doarrayboundscheckingif(n<0||n>size-1){cout<<"下标超界”;return;}

//returntheelementfromtheprivatearraylist

returnalist[n];}

//强制类型转换,将当前对象

//变成指向它的首地址的指针,

//pointerconversionoperatortemplate<classT>Array<T>::operatorT*()const{//returnaddressofprivatearrayinthe//currentobject

returnalist;}//取当前对象的长template<class

T>intArray<T>::ListSize()const{

returnsize;}//改变当前对象的长度

//resizeoperatortemplate<class

T>voidArray<T>::Resize(intsz){//testnewsizeparameter;terminateifsize<=0

if(sz<=0){cout<<“长度不能小于等于0”;return;}

//nothingtodoifsizehasn'tchanged

if(sz==size)return;

//requestnewmemoryandverifysystemresponse

T*newlist=newT[sz];if(newlist==0){cout<<“内存不够”;return;}

intn=(sz<=size)?sz:size;//n取较小的一个

//copynarrayitemsfromoldtonewmemory

T*srcptr=alist;//addressatstartofalist

T*destptr=newlist;//addressatstartofnewlist

while(n--)//copylist*destptr++=*srcptr++;

delete[]alist;//deleteoldlist

//resetalisttopointatnewlistandupdatethesizealist=newlist;size=sz;}ostream&operator<<(ostream&out,constArray<T>&a){for(inti=0;i<a.size;i++)

out<<a.alist[i]<<‘’;

out<<endl;}//通用数组类的测试#include<iostream.h>#include

"array.h"voidmain(void){Array<int>a(20);//定义长为0的整数数组

for(inti=0;i<20;i++)a[i]=i+1;//下标函数返回值是类型T的引用//可以写在表达式的左边

Array<int>b(a),c=a;//用拷贝构造函数,//赋值函数建立新对象

cout<<a<<b<<c;}还可以定义字符数组,记录类型数组,复数类的数组,二维数组,三维数组等等,方法与C语言相同。#include<iostream.h>#include"array.h"#include“complex.h"voidmain(void){Array<complex>a(20);complexs(1,2);for(inti=0;i<20;i++)

a[i]=a[i]+s;Array<complex>b(a),c=a;cout<<a<<b<<c;}3.多于一个参数的模版模版可以有不止一个参数,可以是某个简单类型参数,也可以是通用参数。例

template<classT,classS>

classNode

{Node<T,S>*previous,*next;

T*T_data;

S*S_data;

Public:

Node(Node<T,S>*,Node<T,S>*,T*,S*);~Node();}template<classT,classS>Node<T,S>::Node(Node<T,S>*p,

Node<T,S>*q,T*t,S*s)

{previous=p;next=q;T_data=t;S_data=s;}template<classT,classS>Node<T,S>::~Node()

{deleteT_data;deleteS_data;}4.类模版可以嵌套

template<classT,classS>classList{Node<T,S>*head,*current;public:List();voidInsert(T*,S*);voidRemove(T*,

S*);

~List();}四、类的继承简单继承多重继承多态性和虚函数简单继承

1.派生类的定义2.基类成员的引用和访问的规则3.导出类的构造函数4.覆盖作用域分辨5.派生类的类型转换6.导出类的指针简单继承从一个类可以派生出新的类——派生类或导出类,也叫子类.原来的类叫基类也叫父类.1.派生类的定义形式class新类名:public基类名//公有继承{·········};class新类名:private基类名//私有继承

{·········};

//缺省为私有继承,//基类是struct类时缺省是公有继承基类中的成员自动成为导出类的成员。基类限制词:public和private指明基类成员在导出类中的访问限制classAclassB:publicAclassC:publicB例:classroadVehicle{intwheels,passengers;public:

roadVehicle(int,int); voidSetWheels(intnum); voidSetPassengers(intnum); intGetWheels(void); intGetPassengers(void);voidprint(){cout<<“\nwheels=”<<wheels<<“\nPassengers=”<<passengers;}};

classtruck:public

roadVehicle{intcargo;public:

truck(int,int,int);voidSetCargo(intsize);intGetCargo(void);voidShow(void);voidprint();};Truck类有三个数据成员:wheels,passengerscargo.有9个成员函数1。构造函数和析构函数2。重载的操作符和赋值符3。友元不继承的部分基类中同名的成员被派生类中相应的名字覆盖2.基类成员的引用和访问的规则classAclassB:publicAclassC:publicBprivate不可见不可见protectedprotectedprotectedpublicpublicpublicclassAclassB:privateAclassC:privateBprivate不可见不可见protectedprivate不可见publicprivate不可见保护成员protected数据在基类中同private公有基类的保护成员和公有成员是导出类的保护和公有成员私有基类的保护成员和公有成员是导出类私有成员基类的私有成员在导出类中不可见只能通过基类的公有成员函数调用例voidtruck::print(void){cout<<“\nwheels=”<<wheels

//出错

<<“\npassengers=”<<passengers

//出错<<“\ncargo=”<<cargo;}应改为voidtruck::print(void){roadVehicle::print();cout<<“\ncargo=”<<cargo;}3.导出类的构造函数派生类不继承构造函数和析构函数派生类的构造函数必须包含基类构造函数的信息要为基类构造函数提供初始化参数classtruck的构造函数:truck::truck(inta,intb,intc):roadVahicle(a,b)如果roadVehicle类中roadVehicle::roadVehicle(intx,inty){wheels=x;passengers=y;}则truck类中truck::truck(inta,intb,intc):roadVehicle(a,b){cargo=c;}

注意:导出类的构造函数中未写明基类构造函数基类构造函数的参数无法传递,这时导出类自动调用基类的无参构造函数,如果基类没有无参构造函数,就会出错。如果派生类中还有基类的对象成员classtruck:publicroadVehicle{intcargo;roadVehiclea;public:

truck(int,int,int,int,int);

truck(intx):roadVehicle(x,x+1),a(x,x){cargo=x;}voidSetCargo(intsize);intGetCargo(void);voidShow(void);voidprint();};例truck类的构造函数truck::truck(inta1,inta2,intb1,intb2,intc):roadVehicle(a1,a2),a(b1,b2){cargo=c;}基类的构造函数由基类名标出对象成员的构造函数由对象名标出构造函数的调用顺序

先基类再导出类析构函数相反4.覆盖作用域分辨基类中同名的成员被派生类中相应的名字覆盖例classA{······public:······intfun(){return1;}}classB:publicA{······public:······intfun()//覆盖A中同名元{return2;}}Aa;Bb;inti=a.fun();//i=1intj=b.fun();//j=2

i=b.A::fun();//i=1作用域分辨classB:publicA{······public:······intfun(){return2;}intf(){returnA::fun();}}Bb;inti=b.fun();//i=2intj=b.f();//i=1例truck类中的print函数voidtruck::print(void){roadVehicle::print();cout<<“\ncargo=”<<cargo;}truckt(4,3,4);

t.print();

输出:wheels=4passengers=3cargo=45.派生类的类型转换classA{······};classB:publicA{······};B是A的派生类,B是A的超集可以将类B的对象自动转换为A类对象,反之不成立.Aa;Bb;A*ap=newA;B*bp=newB;a=b;//正确ap=bp;//正确b=a;//错误bp=ap;//错误用户定义类型转换类型转换函数重载X::operatorT();X是原定义类型,T是转换后类型。不带参数,没有返回类型。T就是返回类型。例String::operatorchar*(void){returnstr;}operatorchar*(void)是String类的成员函数String类对象可以作char*字符串类型使用。X::operatorT();X类对象可以作T类型使用Xs;Ta=s;//隐式转换用于初始化Tfun(Tt);

a=fun(s);//隐式转换用于函数参数Xf(Xt);

a=f(s);//隐式转换用于函数返回值

隐式类型转换的规则:用于初始化,函数参数,函数返回值1.标准转换优先(转换成标准类型)。2.不允许转换再转换3.必须唯一确定,不能有二义性。不能用隐式类型转换时用强制类型转换a=T(s);//显式转换强制类型转换6.导出类的指针1公有基类指向导出类对象的指针可以隐式转换为指向基类对象的指针反之不成立

classA{······};classB:publicA{······};A*ap=newA;B*bp=newB;ap=bp;//正确bp=ap;//错误bp=(B*)ap;//正确,//显式转换2.私有基类——不能隐式转换多重继承classA;classB;classC:publicA,publicB{······};1.多重继承的定义由多个基类派生出一个类每个基类都应有自己的存定符A,B的成员都自动成为C的成员,存取权限同单继承classAclassBclassC2.构造函数导出类的构造函数要为基类提供初始化参数方法与单继承相同。调用时先基类再导出类。基类的次序从左到右。C::C(inta,intb,intc):A(a),B(b){······}3.二义性和覆盖两个基类中有同名成员都被继承。导出类对象调用时出现二义性,要用类名域加以区别。也可以在导出类中定义一个同名成员加以覆盖,消除二义性。classAclassBclassCclassA{public:voidf();};classB{public:voidf();};classC:publicA,publicB{public:······};Cc;c.f();//二义性A的f,B的f?c.A::f();//合法c.B::f();//合法classA{public:voidf();};classB{public:voidf();};classC:publicA,publicB{public:······};Cc;c.f();

//二义性A的f,B的f?c.A::f();//合法c.B::f();

//合法voidf(){A::f();B::f();}};//合法同时执行两个f4.虚基类一个基类被派生出两个以上导出类,这两个导出类再生成一个多重导出类.在导出类D中,A的一个元素通过两个途径被继承了两次。这种情况叫双重继承。classBclassCclassDclassA虚基类

虚基类定义可以避免双重继承classBclassCclassDclassAclassA;classB:virtualpublicA;classC:virtualpublicA;ClassD:publicB,publicC;这样定义的D类中A的成员只继承一次,可以直接访问A的成员,也可以用任意路径访问。注意基类的所有直接导出类中都要用virtual声明为虚基类,否则仍然是多重继承。classB:virtualAclassC:virtualAclassDclassA构造函数的调用次序先虚基类(依声明次序从左到右)后非虚基类(依声明次序)编制学校全体教职员工人员卡在校人员学生教师职工

本科生研究生在职研究生兼职教师要求:编号,姓名,性别,出生日期,学生:系,级,三门主课成绩,研究生:专业,导师教师:系,专业,职称,职工:部门,职务输入:10个代表人物,格式化打印多态性和虚函数1.多态性不同的对象调用同一个函数导致不同的操作称为多态性运算符重载和函数重载是最简单的多态性1.动态联编程序在编译时决定由某对象对实例发出的消息,翻译并完成所要求的操作,叫前期装配,或早联编(earlybinding),也叫静态联编。程序在编译时不确定由某对象对实例发出的消息,而是在运行过程中确定由哪个对象实例发出的消息,翻译并完成所要求的操作,叫后期装配,或后联编(laterbinding),也叫动态联编。例classA{char*name;public:

A(char*p){strcpy(name,p);}voidprint(){cout<<“\n”<<name;}};classB:publicA{char*grade;public:B(char*p,inti):A(p){grade=i;}voidprint(){A::print();cout<<“\n”<<grade;}};classC:publicA{char*major;public:

C(char*p,char*q):A(p){strcpy(major,q);}voidprint(){A::print();cout<<“\n”<

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论