子类赋值给父类分三类
。
分别是
1-3
:
1. 子类对象赋值给父类对象 ( 父类对象 = 子类对象 )
2. 子类对象赋值给父类对象的引用 ( & 父类对象 = 子类对象 )
3. 子类对象的地址赋值给父类指针 ( * 父类对象 =& 子类对象 )
1. 子类对象赋值给父类对象 ( 父类对象 = 子类对象 )
2. 子类对象赋值给父类对象的引用 ( & 父类对象 = 子类对象 )
3. 子类对象的地址赋值给父类指针 ( * 父类对象 =& 子类对象 )
4.补充
5.总结
下面分别讲解:
1.赋值
Drived d;
Base b;
b=d;
把等号有右边的子类对象,赋值给等号左边的父类对象时,仅仅是把子类中来自于父类的那一部分成员,赋值给等号左边的父类对象,而赋值完成后,等号左边的对象,依然是父类的对象,依然是父类对象。(初始化父类,就是把两者公共的部分成员赋值给父类,左边的是父类还是父类)
2.引用赋值
下面分别讲解:
1.赋值
Drived d;
Base b;
b=d;
把等号有右边的子类对象,赋值给等号左边的父类对象时,仅仅是把子类中来自于父类的那一部分成员,赋值给等号左边的父类对象,而赋值完成后,等号左边的对象,依然是父类的对象,依然是父类对象。(初始化父类,就是把两者公共的部分成员赋值给父类,左边的是父类还是父类)
2.引用赋值
Derived d;
Base &b=d;
Derived::func();
d.func();//错误
b.func();//不能使用父类引用调用子类扩展成员
把等号右边的子类对象,赋值给等号左边的父类的引用,直接初始化了父类的引用,虽然父类引用了子类对象,但该对象(b)调用该方法(子类继承父类的方法)还是父类的方法。如果不懂,下边有这方面的讲解。还有一点是:父类引用不能调用子类的所扩展的方法。例如:当b调用func()方法会出错,因为b是父类的引用,父类没有这个方法,会出错(尽管它引用了子类对象)。
3.指针赋值
Derived d;
Base *b=&d;
Drived::func(){};
d.func();//正确
b->func();//错误
把等号右边的子类对象的地址,赋值给等号左边的父类的指针,直接初始化了父类的指针,这个和上边的引用类似,直接看例子,父类指针b指向了子类的对象,调用的时候,子类对象可以调用子类扩展的函数,而父类指针调用子类扩展的函数则会出错(原因还是因为父类地没有这个方法,尽管它的指针指向了子类对象)。
4.补充:
当然如果你想通过父类访问子类扩展的也可以,那就必须强转了。
Base * b=new Derived;
Derived::func(){};
//b->func(); error
((Deriverd*)b)->func();//ok, 强制转化
如果父类指针指向子类对象,需要把父类的指针转化为指向子类对象的指针,来访问子类扩展成员这就是所谓的向下转。但是,向下转型是危险的,因为父类指针有可能没有指向子类对象。
总结:
1.左值必须是父类,否则会出现问题,无论它是什么类型的。(父类引用,指针)
2,将子类对象传递给父类的对象,引用或指针,而它的实际值是子类对象,
(例如:
Base &func(Base & b)
{
Derived*p=new Derived;
return*p;//返回值其实还是子类
}
Derivedd;
Base&b=fun(d);
Delete &b; 该函数的返回值是子类 )
3.子类对象转化为父类,向上转型(安全的)
4.父类转化为子类,向下转型(危险的)