继承-基类和派生类的转化

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第7天,点击查看活动详情

.基类和派生类对象赋值转换

  • 派生类对象(子类对象) 可以赋值给 基类的对象 / 基类的指针 / 基类的引用。这里有个形象的说法叫切片或者切割。寓意把派生类中父类那部分切来赋值过去 (赋值兼容规则)

在这个过程中,会发生基类和派生类对象之间的赋值转换。 (子可以赋给父 但是父不可以赋给子,强转也不行)

例子

//基类
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;//子赋给父  切片,此处是深拷贝
}

image-20220313082831582


这里可以形象认为是切片:

派生类对象赋值给基类对象

image-20220312224256847

派生类对象赋值给基类指针

image-20220312224311217

父类指针指向子类对象, 但是父类指针ptr只能看(访问)继承的父类成员,即指向父类的那一部分

派生类对象赋值给基类引用

扫描二维码关注公众号,回复: 14430383 查看本文章

image-20220312224324167

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;//学号
};

父类成员是公有的和保护的,被子类私有继承下来了,访问权限变成私有的,

当我们切割切片子类对象给父类对象/引用/.指针,从父类的角度去看,此时子类成员是保护和公有的!权限变大


父类对象不可以赋值给子类对象  但是指针和引用可以,需要强制类型转化

  • 但是可能会存在越界的风险

    image-20220430155537836

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,不可以访问!
}

\

猜你喜欢

转载自juejin.im/post/7127098636210700318