作用域分辨符主要是为了处理基类和派生类成员的可见性问题。 派生类在继承时,基类成员和派生类成员都有类作用域。两个具有包含关系的作用域,派生类位于内层。当派生类和基类中存在同名的数据成员或函数成员时,派生类的新成员覆盖了基类成员。也就是说在派生类内还是在派生类外部都只能访问到派生类成员,同名基类成员无法访问。 这时我们可以用作用域分辨符来访问基类中的同名成员。基类名限定了后面成员的所属类。语法形式:如果是在派生类外通过派生类对象访问的话,前面还要加上“派生类对象名.”:基类名::数据成员名; // 数据成员 基类名::函数成员名(参数表); // 函数成员
如果多个基类具有同名成员,派生类新增的同名成员同样会将其覆盖。如果派生类中没同名成员,访问多个基类的同名成员也需要作用域分辨符。这是因为从多个基类继承而来的同名成员在派生类中具有相同作用域,成员名无法唯一标识。派生类对象名.基类名::数据成员名; // 数据成员 派生类对象名.基类名::函数成员名(参数表); // 函数成员<span style="font-family: 'Microsoft YaHei';"> </span>
上面讨论的是假设多个基类之间没有继承也没有共同基类的情况。如果派生类的全部或部分基类有共同的基类。那么派生类的直接基类从上一级基类继承而来的成员都有同名成员。要访问他们就必须通过作用域分辨符。#include<iostream> using namespace std; class Base1 { public: voidshow(){cout<<"x of Base1 "<<x<<endl;} intx; //public,不然派生类无法访问 }; class Base2 { public: voidshow(){cout<<"x of Base2 "<<x<<endl;} intx; }; class child : public Base1,public Base2 { public: voidshow(){cout<<"x of child "<<x<<endl;} intx; //同名覆盖 }; int main() { childd; d.x=1; //同名覆盖,child中的x d.show(); d.Base1::x=2; //使用作用域分辨符访问基类Base1类数据成员 d.Base1::show();//使用作用域分辨符访问基类Base1类函数成员 d.Base2::x=3; d.Base2::show(); return0; }
上面代码中,数据成员x在内存中有两份拷贝,当然这两份可以存放不同的数值。但一般我们只需要一份这样的数据,明显造成了内存浪费。解决这个问题我们后面讲到虚基类。#include<iostream> using namespace std; class Base0 { public: voidshow(){cout<<"x of Base1 "<<x<<endl;} intx; //public,不然派生类无法访问 }; class Base1 : public Base0 { }; class Base2 : public Base0 { }; class child:public Base1,public Base2 { }; int main() { childd; d.Base1::x=1; d.Base1::show(); d.Base2::x=2; // 通过直接基类Base1限定成员 d.Base2::show();// 通过直接基类Base1限定成员 return0; }
四十一、继承与派生:作用域分辨符
最新推荐文章于 2023-08-06 20:09:32 发布