C++:同名隐藏和赋值兼容规则
一、同名隐藏
同名隐藏,即在C++的继承中,只要子类的函数名和父类的函数名相同,子类中的函数将会隐藏所有父类中和子类的成员函数同名的函数
特别注意:
和函数之间的重载不同,这里只要求函数的名字相同,而对函数的参数列表是否相同不做要求。话句话说父类中和子类的成员函数名相同但参数列表不同的成员函数也会被隐藏
示例:
1 #include<iostream> 2 using namespace std; 3 class Father{ //父类 4 public: 5 Father()=default; 6 Father(int v):value(v){} 7 void show(){ 8 cout<<"调用Father类中的成员函数show()"<<endl; 9 } 10 void show(int a){ 11 cout<<"调用Father类中的成员函数show(int)"<<endl; 12 } 13 private: 14 int value; 15 }; 16 17 class Son:public Father{ //子类 18 public: 19 Son()=default; 20 Son(int v):value(v){} 21 void show(){ //对父类中的方法show()和方法show(int)进行了同名隐藏 22 cout<<"调用Son类中的成员函数show()"<<endl; 23 } 24 private: 25 int value; 26 }; 27 28 int main(){ 29 Son s; 30 s.show(); 31 //s.show(1); //错误:方法show(int)被同名隐藏了 32 s.Father::show(); //父类的方法show()和方法show(int)确实被子类Son继承了,但被子类Son中的同名方法show()给隐藏了,无法通过子类的对象显式的调用 33 s.Father::show(1); 34 return 0; 35 }
二、赋值兼容规则
所谓赋值兼容规则,即在任何需要基类对象的地方都可以用该基类的公有派生类的对象来代替,它主要包括以下情况:
• 派生类的对象可以赋值给基类的对象,此时的赋值操作主要是把派生类对象中所包含的对应基类的子对象赋值给基类对象
特别注意:
反过来(即将基类对象赋值给派生类对象)不行,因为派生类对象中的新成员将无值可赋
示意图:
示例:
1 #include<iostream> 2 using namespace std; 3 class Father{ //父类 4 public: 5 Father()=default; 6 Father(int value):father_value(value){} 7 void show(){ 8 cout<<"Father类中的成员变量的值为:"<<father_value<<endl; 9 } 10 private: 11 int father_value; 12 }; 13 14 class Son:public Father{ //子类 15 public: 16 Son()=default; 17 Son(int value):Father(value),son_value(value){} 18 void show(){ 19 cout<<"Son类中的成员变量的值为:"<<son_value<<endl; 20 } 21 private: 22 int son_value; 23 }; 24 25 int main(){ 26 Father father(10); 27 Son son(20); 28 father=son; //将派生类对象赋值给基类对象 29 father.show(); 30 return 0; 31 }
• 可以将一个派生类对象的地址赋值给其基类的指针变量
特别注意:
1.只能通过该指针访问派生类中由基类继承来的隐藏对象,不能访问派生类中的新成员
2.此操作的本质是将指针指向派生类中由基类继承来的隐藏对象
3.不能将一个基类对象的地址赋值给一个派生类的指针变量
示意图:
示例:
1 #include<iostream> 2 using namespace std; 3 class Father{ //父类 4 public: 5 Father()=default; 6 Father(int value):father_value(value){} 7 void show(){ 8 cout<<"Father类中的成员变量的值为:"<<father_value<<endl; 9 } 10 private: 11 int father_value; 12 }; 13 14 class Son:public Father{ //子类 15 public: 16 Son()=default; 17 Son(int value):Father(value),son_value(value){} 18 void show(){ 19 cout<<"Son类中的成员变量的值为:"<<son_value<<endl; 20 } 21 void new_func(){ 22 cout<<"调用Son类中的成员方法:new_func()"<<endl; 23 } 24 private: 25 int son_value; 26 }; 27 28 int main(){ 29 Son son(20); 30 Father *ptr=&son;//将派生类对象的地址赋值给基类类型的指针 31 ptr->show(); 32 //ptr->new_func(); //错误:只能通过该指针访问派生类中由基类继承来的隐藏对象,不能访问派生类中的新成员 33 return 0; 34 }
• 派生类对象可以初始化基类的引用
特别注意:
1.只能通过该引用访问派生类中由基类继承来的隐藏对象,不能访问派生类中的新成员
2.此操作的本质是为派生类中由基类继承来的隐藏对象起一个别名
3.不能用基类对象来初始化派生类的引用
示意图:
示例:
1 #include<iostream> 2 using namespace std; 3 class Father{ //父类 4 public: 5 Father()=default; 6 Father(int value):father_value(value){} 7 void show(){ 8 cout<<"Father类中的成员变量的值为:"<<father_value<<endl; 9 } 10 private: 11 int father_value; 12 }; 13 14 class Son:public Father{ //子类 15 public: 16 Son()=default; 17 Son(int value):Father(value),son_value(value){} 18 void show(){ 19 cout<<"Son类中的成员变量的值为:"<<son_value<<endl; 20 } 21 void new_func(){ 22 cout<<"调用Son类中的成员方法:new_func()"<<endl; 23 } 24 private: 25 int son_value; 26 }; 27 28 int main(){ 29 Son son(20); 30 Father &father=son;//用派生类来初始化基类的引用 31 father.show(); 32 //father.new_func(); //错误:只能通过该引用访问派生类中由基类继承来的隐藏对象,不能访问派生类中的新成员 33 return 0; 34 }