继承-基类和派生类的转化
2.基类和派生类对象赋值转换
- 派生类对象(子类对象) 可以赋值给 基类的对象 / 基类的指针 / 基类的引用。这里有个形象的说法叫切片或者切割。寓意把派生类中父类那部分切来赋值过去 (赋值兼容规则)
在这个过程中,会发生基类和派生类对象之间的赋值转换。 (子可以赋给父 但是父不可以赋给子,强转也不行)
例子
//基类
class Person
{
protected:
string _name; //姓名
string _sex; //性别
int _age; //年龄
};
//派生类
class Student : public Person
{
protected:
int _stuid; //学号
};
int main()
{
Student s;
Person p = s; //派生类对象赋值给基类对象
Person* ptr = &s; //派生类对象赋值给基类指针
Person& ref = s; //派生类对象赋值给基类引用
//s = (Student)p; //err 不存在用户定义的从 "Person" 到 "Student" 的适当转换
}
//基类
class Person
{
public:
string _name; //姓名
string _sex; //性别
int _age; //年龄
};
//派生类
class Student : public Person
{
protected:
int _stuid; //学号
};
int main()
{
Person p;
Student s;
s._name = "Mango";
s._sex = "female";
s._age = 19;
p = s;//子赋给父 切片,此处是深拷贝
}
这里可以形象认为是切片:
派生类对象赋值给基类对象
派生类对象赋值给基类指针
父类指针指向子类对象, 但是父类指针ptr只能看(访问)继承的父类成员,即指向父类的那一部分
派生类对象赋值给基类引用
ref成为父类那一部分的别名
注意:
-
基类对象不能赋值给派生类对象
-
基类的指针可以通过强制类型转换赋值给派生类的指针。但是必须是基类的指针是指向派生类对象时才 是安全的。 这里基类如果是多态类型,可以使用RTTI(Run-Time Type Information)的dynamic_cast 来 进行识别后进行安全转换。(ps:这个我们有会讲,这里了解一下)
-
子类赋值给赋给的父类对象/指针/引用,这里不存在类型转化,是语法天然支持的行为
-
如果是类型转化,就不能引用了,因为类型转化中间会产生临时变量,临时变量具有常性,不能修改!
int i = 1; double d = 2.2; //i = d;//err,类型转化中间会产生临时变量 const int& ri = d;//临时变量具有常性,不能修改,
-
这种赋值只适用与公有继承,为什么?
原因:可能发生权限的转化:
例子:
class Person
{
protected:
string _name;//姓名
string _sex;///性别
public:
int _age;//年龄
};
//私有继承父类
class Student :private Person
{
public:
int _Num;//学号
};
父类成员是公有的和保护的,被子类私有继承下来了,访问权限变成私有的,
当我们切割切片子类对象给父类对象/引用/.指针,从父类的角度去看,此时子类成员是保护和公有的!权限变大
父类对象不可以赋值给子类对象 但是指针和引用可以,需要强制类型转化
-
但是可能会存在越界的风险
int main()
{
/*
Student s;
Person p;
//父类对象不可以赋值给子类对象,强制类型转化也不可以
//s = p;
//s = (Student)p;
*/
//但是指针和引用可以
Person p;
Student* pptr = (Student*)&p;
Student& rref = (Student&)p;
//但是存在越界的风险:
//pptr->_Num = 1;//程序崩溃
return 0;
}
如果父类的私有成员被子类继承下来,然后可以进行切片后的指针/引用吗? 如果可以,可以通过切片后的父类的指针/引用访问父类的私有成员吗?
父类的私有成员在子类不可见,但是切片仍然可以完成! 但是切片的父类的指针/引用无法访问父类的私有成员
class Person
{
protected:
string _name;//姓名
string _sex;///性别
private: //此时_age是父类的私有成员!!
int _age;//年龄
};
//私有继承父类
class Student :public Person
{
public:
int _Num;//学号
};
int main()
{
Student s;
Person p;
p = s;
Person* ptr = &s;
Person& ref = s;
ptr->_age = 1; //err,不可以访问!
}
\
- 点赞
- 收藏
- 关注作者
评论(0)