第四十八课、同名覆盖引发的问题

一、子类对象可以当做父类对象使用(兼容性)

1、子类对象可以直接赋值给父类对象

2、子类对象可以直接初始化父类对象

3、父类指针可以直接指向子类对象

4、父类引用可以直接引用子类对象

5、当父类指针(引用)指向子类对象时:

(1)、子类对象退化为父类对象

(2)、只能访问父类中定义的成员

(3)、可以直接访问被子类覆盖的成员

 

#include<iostream>

using namespace std;

class Parent
{
public:
    int mi;
    void add(int v)
    {
        mi += v;
    }
};

class Child : public Parent
{
public:    
    int mv;
    void add(int x, int y)
    {
        mv = (x + y);
    }

};

int main()
{
    Child c;
    Parent p(c);//子类对象可以直接初始化父类对象
    
    Parent p1;
    p1 = c;//子类对象可以直接赋值给父类对象
    
    Parent &rp = c;
    Parent *pp = &c;//父类对象的指针(引用)指向子类对象,使其退化为父类对象

    rp.mi = 100;
    rp.add(1);//可以直接访问被子类覆盖的成员
    cout << pp->mi << endl;//101
    
//    pp->mv = 1000;//已退化成父类对象,只能访问父类对象中的成员
//    pp->add(100, 1);
    return 0;
}

 

二、函数重写与赋值兼容

1、函数重写

(1)、子类中可以定义父类中已经存在的成员函数

(2)、这种重定义发生在继承中,叫做函数重写

(3)、函数重写是同名覆盖的一种特殊情况

 

2、当函数重载遇上赋值兼容

 (1)、编译期间,编译器只能根据指针的类型判断所指向的对象

(2)、根据赋值兼容,编译器认为父类指针指向的是父类对象

(3)、因此,编译结果只能是调用父类中定义的成员函数

#include<iostream>

using namespace std;

class Parent
{
public:
    int mi;
    void add(int v)
    {
        mi += v;
    }
    void print()
    {
        cout << "I'm Parent" << endl;
    }
};

class Child : public Parent
{
public:    
    int mv;
    void add(int x, int y)
    {
        mv = (x + y);
    }

    void print()
    {
        cout << "I'm Child" << endl;
    }

};

void how_to_print(Parent* p)//父类的指针
{
    p->print();
}
int main()
{
    Parent p;
    Child c;

    how_to_print(&p);//期望是I'm Parent, 结果是I'm Parent
    how_to_print(&c);//期望是I'm Child, 结果是I'm Parent
    return 0;
}

 

三、小结

1、子类对象可以当做父类对象使用(赋值兼容

2、父类指针可以正确指向子类对象

3、父类引用可以正确的代表子类的对象

4、子类中可以重写父类中的成员函数

 

posted @ 2017-02-05 16:59  lgc202  阅读(265)  评论(0编辑  收藏  举报