C++类的继承和派生

继承:保留利用原有的类的功能;      派生:添加新的成员和功能。

派生类的构成:吸收基类成员、改造基类成员、添加新的成员。默认情况下派生类包含了全部基类函数中除构造函数和析构函数之外的所有成员,C++11规定可以用using语句继承基类构造函数。

一、继承方式

不同的继承方式的影响主要体现在:

  1、派生类成员对基类成员的访问权限;

  2、通过派生类对象对基类成员的访问权限。

对于派生类的成员或者派生类对象访问自己类的成员不讨论,跟一般类一样,下面只讨论对基类的成员的访问。

public:继承的访问控制:1、基类的public和protected成员:访问属性在派生类中保持不变;

              2、基类的private成员:不可直接访问。

      访问权限:1、派生类的成员函数,可以直接访问基类中的public和protected成员,但不能直接访问基类的private成员;

           2、通过派生类的对象,只能访问public成员。

private:继承的访问控制:1、基类的public和protected成员,都以private身份出现在派生类中;

             2、基类的private成员:不可直接访问。

     访问权限:1、派生类的成员函数,可以直接访问基类中的public和protected成员,但不能直接访问基类的private成员;(调用基类的函数时,可用base::test().)

          2、通过派生类的对象,不能访问从基类继承的任何成员。

protected:继承的访问控制:1、基类的public和protected成员:都以protected身份出现在派生类中;

                    2、基类的private成员:不可直接访问。

            访问权限:1、派生类的成员函数,可以直接访问基类中的public和protected成员,但不能直接访问基类的private成员;

               2、通过派生类的对象,不能访问从基类继承的任何成员。

 

二、基类与派生类类型转换

1、公有派生类对象可以被当作基类的对象使用,反之则不可。

  派生类的对象可以隐式转换为基类对象;

  派生类的对象可以初始化基类的引用;

  派生类的指针可以隐式转换为基类的指针。

2、通过基类对象名、指针只能使用从基类继承的成员、不能使用派生类的成员。(下面例子)

#include <iostream>
using namespace std;

class Base1 { //基类Base1定义
public:
    void display() const {
        cout << "Base1::display()" << endl;
    }
};

class Base2: public Base1 { //公有派生类Base2定义
public:
    void display() const {
        cout << "Base2::display()" << endl;
    }
};

class Derived: public Base2 { //公有派生类Derived定义
public:
    void display() const {
        cout << "Derived::display()" << endl;
    }
};

void fun(Base1 *ptr) {  //参数为指向基类对象的指针
    ptr->display();     //"对象指针->成员名"
}

int main() {    //主函数
    Base1 base1;    //声明Base1类对象
    Base2 base2;    //声明Base2类对象
    Derived derived;    //声明Derived类对象

    fun(&base1);    //用Base1对象的指针调用fun函数
    fun(&base2);    //用Base2对象的指针调用fun函数
    fun(&derived); //用Derived对象的指针调用fun函数

    return 0;
}

建议不要重新定义继承而来的非虚函数!

 

三、派生类的构造和析构

默认情况下,基类的构造函数不被继承,派生类需要定义自己的构造函数。

C++11规定,可用using语句继承基类构造函数;但是只能初始化从基类继承的成员。语法形式:  using Base::Base;

若不继承基类的构造函数:

  派生类新增成员:派生类定义构造函数初始化;

  继承来的成员:自动调用基类构造函数进行初始化;

  派生类的构造函数需要给基类的构造函数传递参数;

样例:

#include<iostream>
using namespace std;

class B {
public:
    B();
    B(int i);
    ~B();
    void print() const;
private:
    int b;
};

B::B() {
    b = 0;
    cout << "B's default constructor called." << endl;
}
B::B(int i) {
    b = i;
    cout << "B's constructor called." << endl;
}
B::~B() {
    cout << "B's destructor called." << endl;
}
void B::print() const {
    cout << b << endl;
}

class C : public B {
public:
    C();
    C(int i, int j);
    ~C();
    void print() const;
private:
    int c;
};

C::C() {
    c = 0;
    cout << "C's default constructor called." << endl;
}
C::C(int i, int j) : B(i), c(j){
    cout << "C's constructor called." << endl;
}
C::~C() {
    cout << "C's destructor called." << endl;
}
void C::print() const {
    B::print();
    cout << c << endl;
}

int main() {
    C obj(5, 6);
    obj.print();
    return 0;
}

 

执行顺序样例:

#include <iostream>
using namespace std;

class Base1 {//基类Base1,构造函数有参数
public:
    Base1(int i)
    {
        cout << "Constructing Base1 " << i << endl;
    }
};

class Base2 {//基类Base2,构造函数有参数
public:
    Base2(int j)
    {
        cout << "Constructing Base2 " << j << endl;
    }
};

class Base3 {//基类Base3,构造函数无参数
public:
    Base3()
    {
        cout << "Constructing Base3 *" << endl;
    }
};

class Derived : public Base2, public Base1, public Base3 {
public:
    Derived(int a, int b, int c, int d) : Base1(a), member2(d), member1(c), Base2(b)
        //此处的次序与构造函数的执行次序无关
    {
        cout << "Constructing Derived" << endl;
    }
private:
    Base1 member1;
    Base2 member2;
    Base3 member3;
};

int main() {
    Derived obj(1, 2, 3, 4);
    return 0;
}

 派生类的复制构造函数:

派生类的析构函数:

样例:

#include <iostream>
using namespace std;

class Base1 {
public:
    Base1(int i)
    {
        cout << "Constructing Base1 " << i << endl;
    }
    ~Base1() { cout << "Destructing Base1" << endl; }
};

class Base2 {
public:
    Base2(int j)
    {
        cout << "Constructing Base2 " << j << endl;
    }
    ~Base2() { cout << "Destructing Base2" << endl; }
};

class Base3 {
public:
    Base3() { cout << "Constructing Base3 *" << endl; }
    ~Base3() { cout << "Destructing Base3" << endl; }
};

class Derived : public Base2, public Base1, public Base3 {
public:
    Derived(int a, int b, int c, int d) : Base1(a), member2(d), member1(c), Base2(b)
    { }
    ~Derived(){ cout << "Destructing Derived" << endl; }
private:
    Base1 member1;
    Base2 member2;
    Base3 member3;
};

int main() {
    Derived obj(1, 2, 3, 4);
    return 0;
}

 

四、派生类成员的标识与访问

#include <iostream>
using namespace std;

class Base1 {
public:
    int var;
    void fun() { cout << "Member of Base1" << endl; }
};

class Base2 {
public:
    int var;
    void fun() { cout << "Member of Base2" << endl; }
};

class Derived : public Base1, public Base2 {
public:
    int var;
    void fun() { cout << "Member of Derived" << endl; }
};

int main() {
    Derived d;
    Derived *p = &d;

    //访问Derived类成员
    d.var = 1;
    d.fun();

    //访问Base1基类成员
    d.Base1::var = 2;
    d.Base1::fun();

    //访问Base2基类成员
    p->Base2::var = 3;
    p->Base2::fun();

    return 0;
}

将上述案例稍作改动:

#include <iostream>
using namespace std;

class Base1 {
public:
    int var;
    void fun() { cout << "Member of Base1" << endl; }
};

class Base2 {
public:
    int var;
    void fun() { cout << "Member of Base2" << endl; }
};

class Derived : public Base1, public Base2 {
public:
    int var;
    void fun() { cout << "Member of Derived" << endl; }
};

int main() {
    Derived d;
    Base1 *p = &d;

    //访问Derived类成员
    d.var = 1;
    d.fun();

    //访问Base1基类成员
    d.Base1::var = 2;
    d.Base1::fun();

    //访问Base2基类成员
    p->Base1::var = 3;
    p->Base1::fun();

    return 0;
}

我们可以发现,如果用base1的指针指向它的子类对象,那么它调用的其实是base1的fun()函数。 

#include <iostream>
using namespace std;

class Base0 {   //定义基类Base0
public:
    int var0;
    void fun0() { cout << "Member of Base0" << endl; }
};

class Base1 : public Base0 { //定义派生类Base1 
public: //新增外部接口
    int var1;
};

class Base2 : public Base0 { //定义派生类Base2 
public: //新增外部接口
    int var2;
};

class Derived : public Base1, public Base2 {
public:
    int var;
    void fun()
    {
        cout << "Member of Derived" << endl;
    }
};

int main() {    //程序主函数
    Derived d;
    d.Base1::var0 = 2;
    d.Base1::fun0();
    d.Base2::var0 = 3;
    d.Base2::fun0();
    return 0;
}

 虚基类:

#include <iostream>
using namespace std;

class Base0 {
public:
    int var0;
    void fun0() { cout << "Member of Base0" << endl; }
};

class Base1 : virtual public Base0 {
public:
    int var1;
};

class Base2 : virtual public Base0 {
public:
    int var2;
};

class Derived : public Base1, public Base2 {
    //定义派生类Derived 
public:
    int var;
    void fun() {
        cout << "Member of Derived" << endl;
    }
};

int main() {
    Derived d;
    d.var0 = 2; //直接访问虚基类的数据成员
    d.fun0();     //直接访问虚基类的函数成员
    return 0;
}

#include <iostream>
using namespace std;

class Base0 {
public:
    Base0(int var) : var0(var) { }
    int var0;
    void fun0() { cout << "Member of Base0" << endl; }
};

class Base1 : virtual public Base0 {
public:
    Base1(int var) : Base0(var) { }
    int var1;
};

class Base2 : virtual public Base0 {
public:
    Base2(int var) : Base0(var) { }
    int var2;
};

class Derived : public Base1, public Base2 {
public:
    Derived(int var) : Base0(var), Base1(var), Base2(var)
    { }
    int var;
    void fun()
    {
        cout << "Member of Derived" << endl;
    }
};

int main() {    //程序主函数
    Derived d(1);
    d.var0 = 2; //直接访问虚基类的数据成员
    d.fun0();   //直接访问虚基类的函数成员
    return 0;
}

 

转载于:https://www.cnblogs.com/maider/p/11352260.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值