一、静态类型决定了可访问的成员
基类的对象、指针和引用的静态类型决定了可以访问哪些成员,即使通过基类的指针或者引用指向一个子类对象,也不能通过基类的指针或引用访问子类对象的成员
示例
class base
{
public:
base(){cout<<__func__<<endl;}
~base(){cout<<__func__<<endl;}
void funcb() {cout<<__func__<<endl;}
};
class derive:public base
{
public:
derive(){cout<<__func__<<endl;}
~derive(){cout<<__func__<<endl;}
void funcd() {cout<<__func__<<endl;}
};
int main(int argc, char const *argv[])
{
base *pb=new derive();
pb->funcd();
return 0;
}
二、继承体系中,成员调用的查找过程
1.确定对象,指针或者引用的静态类型
2.在静态类型对应的类中查找要调用的成员,找到了,查找结束,执行第4步;否则执行第3步
3.依次在直接基类中查找要调用的成员,知道查找到最上面的基类,找到了,查找结束,执行第4步;否则编译器爆报错
4.如果找到了且可以调用,那么还要分3种情况:
4.1.如果是普通的成员变量,那么直接访问
4.2.如果是虚成员函数且是通过指针或引用进行调用的,那么编译器将在运行时决定根据指针或引用的动态类型来调用对应的虚成员函数
4.3.如果是通过对象进行调用的或者调用的不是虚函数,那么编译器将进行普通的函数调用
示例
class base
{
public:
base(){cout<<__func__<<endl;}
~base(){cout<<__func__<<endl;}
virtual void vfunc() {cout<<__func__<<"in base"<<endl;}
void func() {cout<<__func__<<"in base"<<endl;}
int pub=1;
};
class derive:public base
{
public:
derive(){cout<<__func__<<endl;}
~derive(){cout<<__func__<<endl;}
virtual void vfunc() {cout<<__func__<<"in derive"<<endl;}
void func() {cout<<__func__<<"in derive"<<endl;}
};
int main(int argc, char const *argv[])
{
derive d;
base *pb=&d;
pb->vfunc();
base &rb=d;
rb.func();
d.func();
cout<<d.pub<<endl;
return 0;
}
因为vfunc是虚函数,而pb的动态类型是derive,所以调用的是derive的vfunc,而func不是虚函数,即使rb的动态类型是derive,也会依然调用base中的func,调用pub是,发现子类中没有,于是去基类中找
三、当基类和子类出现同名成员
1.基类和子类中出现同名的成员变量
示例
class base
{
public:
base(){cout<<__func__<<endl;}
~base(){cout<<__func__<<endl;}
void func() {cout<<__func__<<"in base"<<endl;}
int pub=1;
};
class derive:public base
{
public:
derive(){cout<<__func__<<endl;}
~derive(){cout<<__func__<<endl;}
void func() {
cout<<__func__<<"in derive"<<endl;
cout<<pub<<endl;
cout<<base::pub<<endl;
}
int pub=2;
};
int main(int argc, char const *argv[])
{
derive d;
base *pb=&d;
pb->func();
d.func();
return 0;
}
当基类和子类中出现相同的成员变量是,如果在子类中访问成员变量,会直接找到子类中的同名变量,不会调用基类中的同名变量。如果想调用基类中的成员变量,需要通过作用域运算符来调用
2.基类和子类中出现同名且参数列表相同的非虚成员函数
同基类和子类中出现同名的成员变量
3.基类和子类中出现同名且参数列表不同的成员函数
示例
class base
{
public:
base(){cout<<__func__<<endl;}
~base(){cout<<__func__<<endl;}
void func(int init) {cout<<__func__<<"in base"<<endl;}
};
class derive:public base
{
public:
derive(){cout<<__func__<<endl;}
~derive(){cout<<__func__<<endl;}
void func() {
cout<<__func__<<"in derive"<<endl;
}
};
int main(int argc, char const *argv[])
{
derive d;
base *pb=&d;
pb->func(10);
d.func(10);
return 0;
}
第24行报错,因为编译器首先在子类中找到了func函数,所以就不会继续再找下去了,但是发现参数列表不匹配,所以报错
如果想正确调用基类中的func,需要使用作用域运算符指定作用域
d.base::func(10);
参考
《C++ Primer》
欢迎大家评论交流,作者水平有限,如有错误,欢迎指出