C++继承

晚上坐出租车回家时,没事和师傅闲聊,随口问了句师傅,什么是生活,师傅缓缓的说了一句,我以前不喜欢开车。。。。

----  网易云热评

一、继承

1、概念:通过一种机制表达类型之间共性和特性的方式,利用已有的数据类型来定义新的数据类型,这种机制就是继承.

2、语法:

class 子类:继承方式1 基类1,继承方式2 基类2,...{

        ...

    };

    继承方式:

    -->public(公有继承)

    -->protected(保护继承)

    -->private(私有继承)

#include <iostream>using namespace std;//人类(基类)class Human{public:    Human(const string& name,int age)        :m_name(name),m_age(age){}    void eat(const string& food){        cout << "我在吃" << food << endl;    }    void sleep(int hour){        cout << "我睡了" << hour << "小时"            << endl;    }protected://保护成员可以在类的内部和子类中访问    string m_name;    int m_age;};//学生类(人类派生的一个子类)class Student:public Human{public:    //Human(...):指明基类部分的初始化方式    Student(const string& name,int age,int no)        :Human(name,age),m_no(no){}    void learn(const string& course){        cout << "我在学" << course << endl;    }    void who(void){        cout << "我叫" << m_name << ",今年" <<            m_age << "岁,学号是" << m_no <<            endl;    }private:    int m_no;};//教师类(人类派生的另一个子类)class Teacher:public Human{public:    Teacher(const string& name,int age,        int salary):Human(name,age),                    m_salary(salary){}    void teach(const string& course){        cout << "我在讲" << course << endl;    }    void who(void)const{        cout << "我叫" << m_name << ",今年" <<            m_age << "岁,工资是" << m_salary            << endl;    }private:    int m_salary;};int main(void){    Student s("关羽",30,10011);    s.who();    s.eat("牛肉拉面");    s.sleep(8);    s.learn("孙武兵法");        Teacher t("孙悟空",35,80000);    t.who();    t.eat("桃子");    t.sleep(6);    t.teach("unix系统编程");    //Student*-->Human*:向上造型    Human* ph = &s;    ph->eat("兰州拉面");    ph->sleep(7);    //ph->who();//error    //Human*-->Student*:向下造型(合理)    Student* ps = static_cast<Student*>(ph);    ps->who();    Human h("林黛玉",22);    //Human*-->Student*:向下造型(不合理)    Student* ps2 = static_cast<Student*>(&h);    ps2->who();//危险    //int * pi = new int(100);    //Student* ps3 = (Student*)pi;    //ps3->who();       return 0;}
运行结果:我叫关羽,今年30岁,学号是10011我在吃牛肉拉面我睡了8小时我在学孙武兵法我叫孙悟空,今年35岁,工资是80000我在吃桃子我睡了6小时我在讲unix系统编程我在吃兰州拉面我睡了7小时我叫关羽,今年30岁,学号是10011我叫林黛玉,今年22岁,学号是-858993460

3、子类继承基类的成员:公有、保护、私有

通过子类,可以直接访问基类中的公有成员和保护成员,就如同它们被声明在子类中一样,但基类中的私有成员,受到访问控制属性的影响,继承后不能直接访问,但是可以让基类提供公有或保护的接口函数来间接访问.

注:基类构造函数和析构函数子类无法继承。

#include <iostream>using namespace std;class Base {//基类public:    void public_func(void) {        cout << "基类的公有成员" << endl;    }protected:    void protected_func(void) {        cout << "基类的保护成员" << endl;    }public:    void getPrivate(void) {        private_func();    }private:    void private_func(void) {        cout << "基类的私有成员" << endl;    }};class Derived :public Base {//子类public:    void func(void) {        public_func();        protected_func();        //private_func();//error        getPrivate();    }};int main(void){    Derived d;    d.func();}运行结果:基类的公有成员基类的保护成员基类的私有成员

4、子类隐藏基类的成员

如果子类和基类中定义了同名的成员函数,因为作用域不同,不能构成重载关系,而是一种隐藏关系,当通过子类访问该成员时,将优先访问子类自己的成员。如果需要通过子类访问基类中被隐藏的成员,可以显式的通过"类名::"来指明。

如果形成隐藏关系的成员函数满足不同参的重载条件,也可以通过using声明,将基类中成员函数引入子类作用域,让它们形成有效的重载关系,通过重载匹配来解决//不推荐

#include <iostream>using namespace std;class Base{public:    void func(int i){        cout << "Base::func(int)" << endl;    }};class Derived:public Base{public:    void func(void){        cout << "Derived::func(void)" << endl;    }    //将基类中的func声明到当前子类作用域,让    //它们构成函数重载关系    //using Base::func;};int main(void){    Derived d;    d.Base::func(10);    d.func();    return 0;}运行结果:Base::func(int)Derived::func(void)

5、访问控制限定符:影响访问该类的成员的位置

访问控制      访问控制        内部    子类    外部    友元

限定符          属性              访问    访问    访问    访问

public          公有成员        ok        ok        ok        ok

protected    保护成员        ok        ok        no        ok

private         私有成员        ok        no        no        ok

#include <iostream>using namespace std;class A {//基类public:    int m_public;//公有成员protected:    int m_protected;//保护成员private:    int m_private;//私有成员};class B :public A {//公有继承的子类    void func(void) {        m_public = 123;        m_protected = 123;        //m_private = 123;    }};class C :protected A {//保护继承的子类    void func(void) {        m_public = 123;        m_protected = 123;        //m_private = 123;    }};class D :private A {//私有继承的子类    void func(void) {        m_public = 123;        m_protected = 123;        //m_private = 123;    }};class X :public B {    void foo(void) {        m_public = 123;        m_protected = 123;        //m_private = 123;    }};class Y :public C {    void foo(void) {        m_public = 123;        m_protected = 123;        //m_private = 123;    }};class Z :public D {    void foo(void) {        //m_public = 123;        //m_protected = 123;        //m_private = 123;    }};int main(void){    B b;    b.m_public = 123;//ok    //b.m_protected = 123;    //b.m_private = 123;    C c;    //c.m_public = 123;    //c.m_protected = 123;    //c.m_private = 123;    D d;    //d.m_public = 123;    //d.m_protected = 123;    //d.m_private = 123;    return 0;}

6、子类的构造函数

如果子类的构造函数没有显式指明基类子对象的初始化方式,那么编译器将会自动调用基类的无参构造函数来初始化基类子对象。

如果希望基类子对象以有参的方式被初始化,则必须使用初始化列表。

#include <iostream>using namespace std;class Member{public:    Member(void):m_j(0){        cout << "Member(void)" << endl;    }    Member(int j):m_j(j){        cout << "Member(int)" << endl;    }    int m_j;};class Base{public:    Base(void):m_i(0){        cout << "Base(void)" << endl;    }    Base(int i):m_i(i){        cout << "Base(int)" << endl;    }    int m_i;};class Derived:public Base{public:    Derived(void){        cout << "Derived(void)" << endl;    }    //Base(i):指明基类子对象的初始化方式    //m_mem(i):指明成员子对象的初始化方式    Derived(int i):Base(i),m_mem(i){        cout << "Derived(int)" << endl;    }    Member m_mem;//成员子对象};int main(void){    Derived d;    cout << d.m_i << endl;//0    Derived d2(123);    cout << d2.m_i << endl;//123    return 0;}

7、子类的析构函数

子类的析构函数,无论自己定义的析构函数还是编译器缺省提供的,都会自动调用基类的析构函数,完成基类子对象的销毁。

子类对象的销毁过程:执行子类析构函数的代码,析构成员子对象(按声明逆序),析构基类子对象(按继承表逆序),释放内存

基类的析构函数不能自动调用子类的析构函数,所以对一个指向子类对象的基类指针使用delete操作符,实际被调用的仅是基类的析构函数,子类的析构函数执行不到,有内存泄漏的风险。

#include <iostream>using namespace std;class Member{public:    Member(void):m_j(0){        cout << "Member(void)" << endl;    }    Member(int j):m_j(j){        cout << "Member(int)" << endl;    }    ~Member(void){        cout << "~Member(void)" << endl;    }    int m_j;};class Base{public:    Base(void):m_i(0){        cout << "Base(void)" << endl;    }    Base(int i):m_i(i){        cout << "Base(int)" << endl;    }    ~Base(void){        cout << "~Base(void)" << endl;    }    int m_i;};class Derived:public Base{public:    Derived(void){        cout << "Derived(void)" << endl;    }    //Base(i):指明基类子对象的初始化方式    //m_mem(i):指明成员子对象的初始化方式    Derived(int i):Base(i),m_mem(i){        cout << "Derived(int)" << endl;    }    ~Derived(void){        cout << "~Derived(void)" << endl;    }    Member m_mem;//成员子对象};int main(void){    /* Derived d;    cout << d.m_i << endl;//0    Derived d2(123);    cout << d2.m_i << endl;//123    */        Base* pb = new Derived;    //...    //pb->析构函数    delete pb;//内存泄露问题    return 0;}运行结果:Base(void)Member(void)Derived(void)~Base(void)

 

欢迎关注公众号:顺便编点程

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

web安全工具库

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值