本帖最后由 sunrise085 于 2018-12-20 16:51 编辑
关于类的继承,一定要记住这三种属性的作用范围。public属性的作用域最广,可继承,可访问;protected属性的作用域稍弱,可继承,不可访问;private属性的作用域最小,不可继承,不可访问。以上所说的作用域范围都是在类以外,对于类的成员函数访问类的成员变量或成员函数不受属性范围限制。
下面以你的这个程序为例向你详细解释一下。
在现有的程序中,子类Son继承于父类Father,因父类中的成员变量name属性是protected,因此能够被继承,而且子类Son中没有同名的成员变量,因此成员变量name完全继承于父类Father,在创建子类Son的对象的时候和Father共用一个成员变量name;还有就是Father类的成员函数show,也被继承下来。
先说图一的执行过程:
在执行Son_class tom("tom")的时候,调用Son构造函数,因Son类是继承于Father类,所以在执行Son构造函数之前先执行Father的构造函数,进入Father的构造函数:
在Father的构造函数中,执行第一句后name="aaa",然后执行第二句,输出"now in Father 构造器";
此时tom.name="aaa",但是构造函数还没执行完,接着返回到Son构造函数:
在Son的构造函数中,执行第一句后,输出"Now in Son_class的构造器中",执行第二句,name被修改为"tom",在执行下面的语句时,Son类的对象tom的成员变量name已经是"tom",因此输出Father的name和Son的name都是tom,输出"$$$$$$$$$$$$$"之后,Son构造函数彻底执行完成;
接下来执行第二句, tom.show_name(),调用了从父类Father类中继承来的成员函数show(),输出了"name is tom";
最后程序结束,销毁在main()中创建的Son类对象tom,因此执行Son的析构函数,执行析构函数的顺序与构造函数的顺序相反,先析构子类,再析构父类。
在此程序中,子类Son的构造函数继承时,Father类后面的"aaa"没有任何作用,因为一进入构造函数,就被name1修改了,但是这里又必须要写,因为Father类的构造函数是需要参数了,所以必须写一个参数。
再说一说修改之后的程序。修改之后,Father中的成员变量name属性变为private,无法被继承,而且在子类Son中有一个同名的成员变量,它与Father的name相当于是两个独立的变量(这里为了区别,暂时称之为name_f和name
_s);子类Son中没有成员函数show(),而父类Father类的show()是可以继承的,因此子类Son继承了父类Father的成员函数,但是因为它是父类的成员函数,因此所访问的name是name_f,而不是name_s。
下面我们看一下按程序的执行过程:
在执行Son_class tom("tom")的时候,调用Son构造函数,因Son类是继承于Father类,所以在执行Son构造函数之前先执行Father的构造函数,进入Father的构造函数:
在Father的构造函数中,执行第一句后name_f被赋值"aaa",然后执行第二句,输出"now in Father 构造器";
此时name_f="aaa",但是构造函数还没执行完,接着返回到Son构造函数:
在Son的构造函数中,执行第一句后,输出"Now in Son_class的构造器中",执行第二句,name_s被赋值为"tom",Son类的对象tom的成员变量name已经是"tom",而此时Father的name仍然是"aaa",和Son的name是不一样的,
在执行构造函数第三行时,因为是在Son的构造函数中,因此语句中的name指的是name_s,即"tom",输出"now name of Son_class is : tom",
在执行第四行时,调用成员函数show(),而该函数来自父类,访问的是name_f,因此输出"now name of Father_class is : name is aaa",输出"$$$$$$$$$$$$$"之后,Son构造函数彻底执行完成;
接下来执行第二句, tom.show_name(),调用了从父类Father类中继承来的成员函数show(),因此输出的仍然是Father的成员变量name,输出了"name is aaa";
最后程序结束,销毁在main()中创建的Son类对象tom,因此执行Son的析构函数,执行析构函数的顺序与构造函数的顺序相反,先析构子类,再析构父类。
在修改之后的程序中,因为子类中没有重载父类的show(),因此一直使用的都是父类的函数,不管在调用之前是否添加Father_class::,所以在Son的构造函数中,第五行Father_class ::show_name() ,可以省略前面的Father_class::,效果是一样的。
此外你可以尝试一下,在子类中重载show()函数,然后看看运行结果,调用show()函数时前面是否添加Father_class,结果就不一样了。