面对对象三大特征之一:继承
1)关键字:修饰类的成员(成员变量和成员函数)
a) public关键字:公有成员除了自身和派生类以外,类外也能使用。
b) protected关键字:保护成员除了自身或者派生类以外,不能在其他类外使用。
c) private关键字:私有成员除了自身使用以外,不能在派生类和类外使用。
2)继承的可见性
class Cperson
{
public:
int a=1;
protected:
int b=2;
private:
int c=3;
};
class Cstudent1:private Cperson //private继承
{
public:
Cstudent()
{
a = 10; //此刻类外已经不能访问,因为a已经变成儿子的私有成员(private)
b = 11; //b的属性也降为private,已经变成儿子的私有成员(private)
//c = 12; //父类的私有成员儿子无法访问
}
};
class Cstudent2:protect Cperson //protected继承
{
public:
Cstudent()
{
a=10; //此刻类外已经不能访问,因为a已经变成儿子的保护成员(protected)
b=11; //b的属性依旧是protected
//c=12;
}
}
3)继承的可见性在何时做的检查?
是由编译器在编译时刻做的限制,运行时可以通过指针来改变private的值!(不推荐这样做,违背了设计private的初衷,破坏了封装性)
class Cperson //有12个字节
{
public:
int a=1;
protected:
int b=2;
private:
int c=3;
};
class Cstudent:public Cperson //有16个字节,12个字节是从父类继承而来
{
private:
int d=4;
};
int main()
{
Cperson per;
int* p = (int*)((char*)(&per) + 8); //先将per的地址强转为char*,这样+8就代表向后移动八个字节,就由原来指向公有成员a指向现在的私有成员c
*p = 123; //成功在类外改变了私有成员c的值,进一步说明继承仅仅是编译器在编译时做的限制
Cstudent stu; //从内存显示从Cperson继承到的私有成员c的值还是3!此时子类的c和父类的c的值不一样了,打印结果也是3和123!
return 0;
}
4)指针转换的安全性
子类指针转换为父类指针是安全的(因为子类包含父类,内存由大变小,无越界风险)
父类指针转换为子类指针是不安全的(内存由小变大,有越界风险)
(子类转父类,不用指针强转都能编译通过;父类转子类,必须要指针强转才能通过)
class Cperson //有12个字节
{
public:
int a=1;
protected:
int b=2;
private:
int c=3;
};
class Cstudent:public Cperson //有16个字节,12个字节是从父类继承而来
{
private:
int d=4;
};
int main()
{
Cperson per;
Cstudent stu;
Cperson* pPer=&stu; //子类指针转换为父类指针是安全的,不用强转指针,编译器默认通过 !
Cstudent* pStu=(Cstudent*)&per;
//父类指针转换为子类指针是不安全的,必须强转类型,否则编译不通过!
return 0;
}