C++ 继承(1)
1.1定义
1.1引入
从生活中举个例子,继承可以是儿子继承父亲的家业,这就使得儿子可以不用花费任何努力就得到一些东西。C++中也是一样,子类(又叫派生类)可以继承父类(又叫基类)的成员(其中包括成员变量和成员函数)
本质:复用(之前学过下面这些,大都是函数的复用,继承可以理解为类的复用)
- 函数调用(直接调用已定义的函数,这是最基本的复用方式)
- 函数重载(通过定义参数列表不同的同名函数,实现相似功能的复用)
- 函数模板(使用泛型编程实现通用函数,适配不同数据类型)
- 内联函数(在编译时将函数代码嵌入调用处,避免函数调用开销的同时实现复用)
- 库函数(使用标准库或自定义库中已实现的函数)
1.2格式
如上述代码所示,Student类继承Person类
class Student(子类):public(继承方式) Person(父类)
class Person
{
public:void Print(){cout << "name:" << _name << endl;cout << "age_" << _age << endl;}
protected:string _name = "Peter";int _age = 18;};
class Student :public Person
{
protected:int _stuid;
};
1.3继承基类成员访问方式的变化
- 父类的私有成员在子类中无论以什么样的继承方式均不可见(父类的私有成员还是被继承到了派生类对象中,是存在的,但是语法上限制在类内外均无法访问=》但是可以间接访问哦后面讲)
- 父类中的protected:保证了父类成员不想再类外被访问,但是可以在子类访问。
- 使用关键字class时,默认的继承方式是private;使用关键字struct时,默认public;
- protected的只能在子类中访问,不能在其他类中访问
2.赋值兼容转换
子类对象可以赋值给父类的对象,父类指针,父类的引用(但是父类对象不能赋值给子类对象)
class Person
{
protected:string _name;string _sex;int _age;
};
class Student :public Person
{
public:int _No;
};
void Test()
{Student sobj;Person pobj=sobj;//子类对象赋值给父类对象Person* pp = &sobj;//子类对象赋值给父类指针Person& rp = sobj;//子类对象赋值给父类引用//错误,基类对象不能赋值给派生类对象sobj = pobj;//3.基类的指针可以通过强致类型转换赋值给派生类的指针pp = &sobj;Student* ps1 = (Student*)pp;ps1->_No = 10;pp = &pobj;Student* ps2 = (Student*)pp;//可以,但是可能会越界访问ps2->_No = 20;}
3.继承中的作用域
3.1关于隐藏、重定义
隐藏、重定义:子类和父类中有同名成员,子类成员将屏蔽父类成员的直接访问,(在子类成员函数中,可以使用基类::基类成员显示访问)
3.2一个易错点
class A {
public:void Fun(){cout << "Fun()" << endl;}
};
class B:public A
{
public:void Fun(int i){A::Fun();cout << "Fun(int i)->" <<i<< endl;}
};
void Test()
{B b;b.Fun(10);
}
int main()
{Test();return 0;
}
执行结果:
那么,问题,A类中的Fun()和B类中的Fun(i)是否构成函数重载呢
不构成,因为他们不是同一作用域
他们俩构成隐藏,成员函数满足函数名相同就构成隐藏