C++中的继承(3)作用域与重定义,赋值兼容规则
来源:互联网 发布:tensorflow tutorial 编辑:程序博客网 时间:2024/06/07 02:02
作用域与重定义(同名隐藏)
一样的,先上代码
1 class A 2 { 3 public: 4 int a_data; 5 void a() 6 { 7 cout << "A" << endl; 8 } 9 };10 class B11 {12 public:13 int b_data;14 void b()15 {16 cout << "B" << endl;17 }18 };19 class C :public A, public B20 {21 public:22 int c_data;23 void a(int data)//重载A类中的a()函数24 {25 cout << "C" << endl;26 }27 };28 int main()29 {30 C c;31 c.a();32 return 0;33 }
编译后,编译器会报错错误表明:编译器并没有将c.a()看做C类继承自A类的a()函数,而是报错没有给a函数参数,即不构成函数重载,如果给c.a(10)一个参数,编译通过。输出:C
那么我们不给C类中定义同名函数呢
1 class A 2 { 3 public: 4 int a_data; 5 void a() 6 { 7 cout << "A" << endl; 8 } 9 };10 class B11 {12 public:13 int _data;14 void b()15 {16 cout << "B" << endl;17 }18 };19 class C :public A, public B20 {21 public:22 int _data;23 //void a(int data)24 //{25 // cout << "C" << endl;26 //}27 };28 int main()29 {30 C c;31 c.a();32 return 0;33 }
编译通过,运行输出:A
以上两个例子,完全可以说明,当我们在派生类中定义一个同名函数的时候,编译器是将同名函数隐藏了,不管参数表是否相同。即不会构成函数重载,直接为函数覆盖。
那么问题来了,为什么不会构成函数重载呢?
一定要注意,函数重载的条件是在同一个作用域中才会构成函数重载,而派生类和基类是两个类域,一定不会构成函数重载的。
当然,我们还有另外一个方法访问同名时基类中的成员即
1 int main() 2 { 3 C c; 4 c._data; 5 c.B::_data; 6 c.a(); 7 c.A::a(); 8 getchar(); 9 return 0;10 }
B类的成员变量_data与C类中的成员变量_data也构成同名隐藏。
1. 在继承体系中基类和派生类是两个不同作用域。
2. 子类和父类中有同名 成员 , 子类成员 将屏蔽父类对成员 的直接访问。 ( 在子类成员 函数中, 可以 使用 基类: : 基类成员 访问) --隐藏 --重定义
3. 注意在实际中在继承体系里面最好不要定义同名 的成员 。
继承与转换——赋值兼容规则(public继承为例)
派生类和基类之间的特殊关系为:
1.派生类对象可以赋值给基类对象 ;基类对象不能赋值给派生类。
2.基类指针可以在不进行显示类型转换的情况下指向派生类对象 。
3.基类引用可以再不进行显示类型转换的情况下引用派生类对象,但是基类指针或引用只能用于调用基类的方法,不能用基类指针或引用调用派生类的成员及方法。
1 void FunTest(const Base&d) 2 {} 3 void FunTest1(const Derive&d) 4 {} 5 int main() 6 { 7 Derive d; 8 Base b(0); 9 b = d;//可以10 d = b;//不行,访问的时候会越界11 //上面已经解释过了12 FunTest(b);13 FunTest(d);14 FunTest1(b); //报错15 FunTest1(d);16 Base* pBase = &d; //父类指针/或引用可以直接指向子类对象,但只能访问子类中继承父类的部分17 Derive* pD = &b;//报错 子类的指针/引用不能直接指向父类对象18 //如果非要这么做只能通过强制类型转换19 Derive* pD = (Derive*)&b;//如果访问越界,程序会崩溃20 }
通常,C++要求引用和指针类型与赋给的类型匹配,但这一规则对继承来说是个例外。但是这个例外是单向的,即仅仅不可以将基类对象和地址赋给派生类引用和指针。如果允许基类引用隐式的引用派生类对象,则可以使用基类引用为派生类对象调用基类的方法,因为派生类继承了基类的方法,所以这样不会出现问题。但是如果可以将基类对象赋给派生类引用,那么派生类引用能够为积累对象调用派生类方法,这样做会出现问题,例如:用基类对象调用派生类中新增的方法,是没有意义的,因为基类对象中根本没有派生类的新增方法。
友元与继承
1 class Person 2 { 3 friend void Display(Person &p, Student&s); 4 protected: 5 string _name; // 姓名 6 }; 7 class Student : public Person 8 { 9 protected :10 int _stuNum; // 学号11 };12 void Display(Person &p, Student &s)13 {14 cout << p._name << endl;15 cout << s._name << endl;16 cout << s._stuNum << endl;17 }18 void TestPerson1()19 {20 Person p;21 Student s;22 Display(p, s);23 }
友元关系不能继承, 也就是说基类友元不能访问子类私有和保护成员 。友元只是能访问指定类的私有和保护成员的自定义函数,不是被指定类的成员,自然不能继承。
使用友元类时应该注意:
(1) 友元关系不能被继承。
(2) 友元关系是单向的,不具有交换性。若类B是类A的友元,类A不一定是类B的友元,要看在类中是否有相应的声明。
(3)友元关系不具有传递性。若类B是类A的友元,类C是B的友元,类C不一定是类A的友元,同样要看类中是否有相应的申明
(4)友元可以访问类的私有成员。
(5)友元只能出现在类定义内部,友元声明可以在类中的任何地方,一般放在类定义的开始或结尾。
(6)友元可以是普通的非成员函数,或前面定义的其他类的成员函数,或整个类。
(7)类必须将重载函数集中每一个希望设为友元的函数都声明为友元。
(8)友元关系不能继承,基类的友元对派生类的成员没有特殊的访问权限。如果基类被授予友元关系,则只有基类具有特殊的访问权限。该基类的派生类不能访问授予友元关系的类。
继承与静态成员
了解这个问题之前,我们先确定一件事情,那就是,在基类和派生类中,静态成员和静态成员函数共用同一段空间。 我们在以前的学习过程中都知道,类的模型是所有对象的数据成员单独存储,但是所有成员函数和静态成员是共用一段空间的
1 class Person 2 { 3 public : 4 Person() {++ _count; } 5 protected : 6 string _name ; // 姓名 7 public : 8 static int _count; // 统计人的个数。 9 } ;10 int Person: : _count = 0;11 class Student : public Person12 {13 protected :14 int _stuNum ; // 学号15 } ;16 class Graduate : public Student17 {18 protected:19 string _seminarCourse; // 研究科目20 } ;21 void TestPerson1()22 {23 Student s1;24 Student s2;25 Student s3;26 Graduate s4;27 cout<<"人数: "<<Person: : _count<<endl;28 Student : : _count = 0;29 cout<<"人数: "<<Person: : _count<<endl;30 }
基类定义了 static成员 , 则整个继承体系里面只 有一个这样的成员 。 无论派生出多少个子类, 都只有 一个static成员 实例。父类的static变量和函数在派生类中依然可用,但是受访问性控制(比如,父类的private域中的就不可访问)。而且对static变量来说,派生类和父类中的static变量是共用空间的,这点在利用static变量进行引用计数的时候要特别注意。派生类的friend函数可以访问派生类本身的一切变量,包括从父类继承下来的protected域中的变量。但是对父类来说,他并不是friend的。
- C++中的继承(3)作用域与重定义,赋值兼容规则
- 继承和多态 1.0 -- 继承概念(is-a、has-a,赋值兼容规则,隐藏重定义)
- 【继承与多态】C++:继承中的赋值兼容规则,子类的成员函数,虚函数(重写),多态
- 【继承与多态】C++:继承中的赋值兼容规则,子类的成员函数,虚函数(重写),多态
- 继承中的支配规则和赋值兼容规则
- 钻石继承、虚基类、赋值兼容规则
- 单定义规则与作用域
- 同名隐藏与赋值兼容规则
- 赋值兼容规则
- 赋值兼容规则
- 赋值兼容规则
- 赋值兼容规则
- 赋值兼容规则
- c++赋值兼容规则
- [c++]基类对象作为函数参数(赋值兼容规则)
- (继承及其访问限定符)&&(派生类及其默认成员函数)&&(赋值兼容规则)
- C 作用域规则
- C++基础:同名隐藏与赋值兼容规则
- PHP socket服务器框架Workerman (GatewayWorker)
- 摄像机摇移跟随
- Redis安装
- 小强ROS机器人教程(17)___利用ORB_SLAM2建立环境三维模型
- Java反射详解
- C++中的继承(3)作用域与重定义,赋值兼容规则
- tensorflow函数--softmax_cross_entropy_with_logits
- BZOJ 1179: [Apio2009]Atm
- (c语言)结构体方法,计算该日是当年的第几天
- 建立HashSet的实例,依次填入三个名字判断实例中是否存在"Kobe"
- C++中的类继承(1) 三种继承方式
- Windows 10 很快变得更安全
- win10 uwp 拖动控件
- vim中文帮助文档安装