[疑问]虚函数与多态性
对于普通成员函数的重载,可表达为下面的方式:
1) 在同一个类中重载
2) 在不同类中重载
3) 基类的成员函数在派生类中重载
因此,重载函数的访问是在编译时区分的,有以下三种方法:
1.根据参数的特征加以区分,例如:
Show(int , char)与Show(char *, float)
不是同一函数,编译能区分。
2. 使用“::”加以区分,例如:
Circle :: Show有别于Point :: Show
3. 根据类对象加以区分。
ACircle.Show() 调用Circle::Show()
APoint.Show() 调用Point :: Show()
这里ACircle和APoint分别是Circle和Point的对象。
注意上图,Derived_Class自己定义的成员,P不能访问
#include <iostream.h>
#include <string.h>
class B_class
{
char name[80]; //默认是私有的吧?!
public :
void put_name(char * s)
{
strcpy(name, s);
}
void show_name( )
{
cout<<name<<"\n";
}
};
class D_class: public B_class
{
char phone_num[80];
public:
void put_phone(char * num)
{
strcpy(phone_num, num);
}
void show_phone( )
{
cout<<phone_num<<"\n";
}
};
main()
{
B_class * p;
B_class B_ob;
D_class * dp;
D_class D_ob;
p=&B_ob;
p->put_name("Thomas Edison");
p=&D_ob;
p->put_name("Albert Einstein");
B_ob.show_name( );
D_ob.show_name( );
dp=&D_ob;
dp->put_phone("555555_1234");
dp->show_phone( );
p->show_pone( ); //错误
((D_class*)p)->show_phone ( );
p->show_phone( ); //错误
}
1.可以用一个指向基类的指针指向其公有派生类的对象。但是相反却不正确,即不能用指向派生类的指针指向一个基类的对象。
2.希望用基类指针访问其公有派生类的特定成员,必须将基类指针用显式类型转换为派生类指针。例如: ((D_class*)p)->show_phone( );
5.3.2 虚函数
#include<iostream.h>
class Base
{
protected:
int x;
public:
Base(int a)
{
x=a;
}
void who()
{
cout<<“base ”<<x<<“n”;
}
};
class First_d: public Base
{
public:
First_d (int a):Base(a){ }
void who()
{
cout<<“First derivation ”<<x<“\n”; //这里的X是什么?
}
};
class Second_d: public Base
{
public:
Second_d (int a):Base(a){ }
void who()
{
cout<<“Second derivation ”<<x<“\n”;
}
};
void main()
{
Base * p;
Base base_obj(1);
First_d first_obj(2);
Second_d second_obj(3);
p=&base_obj;
p->who();
p=&first_obj;
p->who();
p=&second_obj;
p->who();
first_obj.who();
second_obj.who();
}
指向基类的指针p,不管是指向基类的对象base_obj还是指向派生的对象first_obj和second_obj, p->who()调用的都是基类定义的 who()的版本.必须显式地用
first_obj.who();
和
second_obj.who();
才能调用类first_d和类second_d中定义的who()的版本。其本质的原因在于普通成员函数的调用是在编译时静态区分。
例 5-31
#include <iostream.h>
class figure
{
protected:
double x, y;
public:
void set_dim(double i, double j=0)
{
x=i;
y=j;
}
virtual void show_area()
{
cout<<“No area computation defined”;
cout<<“for this class.\n”;
}
};
class triangle : public figure
{
public:
void show_area()
{
cout<<“Triangle with high”;
cout<<x<<“and base”<<y;
cout<<“ has an area of”;
cout<<x*0.5*y<<“\n”;
}
};
class square : public figure
{
public:
void show_area()
{
cout<<“Square with dimension”;
cout<<x<<“*” <<y;
cout<<“has an area of”;
cout<<x * y<<“\n”;
}
};
class circle : public figure
{
public:
void show_area()
{
cout<<“Circle with radius” ;
cout<<x;
cout<<“has an aera of” ;
cout<<3.14* x*x;
}
};
上图中首先调用基类对象中的函数set_dim(int,int),设置的x,y可以在派生类中可见吧???然后是基类调用派生类对象中的函数show_area()
上面的倒数第二行,Bref.fun()是调用class C中的fun()吗? ???这里的Bref是B的引用,又不是指针!