真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

C++中的繼承詳解

[TOC]

目前創(chuàng)新互聯(lián)建站已為上千余家的企業(yè)提供了網(wǎng)站建設(shè)、域名、雅安服務(wù)器托管、網(wǎng)站托管運(yùn)營(yíng)、企業(yè)網(wǎng)站設(shè)計(jì)、恒山網(wǎng)站維護(hù)等服務(wù),公司將堅(jiān)持客戶導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長(zhǎng),共同發(fā)展。

繼承基本知識(shí)

定義:

 繼承是面向?qū)?em>復(fù)用的重要手段。通過(guò)繼承定義一個(gè)類,繼承是類型之間的關(guān)系建模,共享公有的東西,實(shí)現(xiàn)各自本質(zhì)不同的東西。

繼承關(guān)系:

 三種繼承關(guān)系下基類成員的在派生類的訪問(wèn)關(guān)系變化(圖)
C++中的繼承詳解
 舉個(gè)栗子(公有繼承)

```c++
class Person
{
public :
Person(const string& name)
: _name(name )
{}
void Display ()
{
cout<<_name <}
protected :
string _name ; // 姓名
string _sex ;
};

class Student : public Person //公有繼承
{
protected :
int _num ; // 學(xué)號(hào)
};

### 繼承圖例解釋:
![這里寫(xiě)圖片描述](/upload/otherpic46/2018042122253862?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM4NjQ2NDcw/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
**私有繼承和保護(hù)繼承很少用到,我們重點(diǎn)要掌握公有繼承**

### 繼承與轉(zhuǎn)換--賦值兼容規(guī)則--public繼承
1. 子類對(duì)象可以賦值給父類對(duì)象(切割/切片)
2. 父類對(duì)象不能賦值給子類對(duì)象
3. 父類的指針/引用可以指向子類對(duì)象
4. 子類的指針/引用不能指向父類對(duì)象(可以通過(guò)強(qiáng)制類型轉(zhuǎn)換完成)
```C++
class Person
{
public:
    void Display()
    {
        cout << "AA" << endl;
    }
protected:
    string _name; // 姓名
};
class Student : public Person
{
public:
    int _num; // 學(xué)號(hào)
};

int main()
{
    Person a;
    Student b;
    a = b; //子類對(duì)象賦值給基類對(duì)象(切片)這個(gè)特性是編譯器支持的
    b = a; //父類對(duì)象不能賦值給子類對(duì)象

    Person *p1 = &b; //特性3
    //Person &a1 = b; //特性3
    Student *p2 = (Student*)&a; //特性4
    Student& b1 = (Student&)a; //特性4
    getchar();
    return 0;
}

繼承體系中的作用域

  1. 在繼承體系中基類和派生類都有獨(dú)立的作用域。
  2. 子類和父類中有同名成員(成員函數(shù),成員變量)子類成員將屏蔽父類對(duì)成員的直接訪問(wèn)。(在子類成員函數(shù)中,可以使用 基類::基類成員 訪問(wèn))--隱藏(重定義)
  3. ==注意在實(shí)際中在繼承體系里面最好不要定義同名的成員==。
    class Person
    {
    public:
    Person(const char *name = "",int num = 0)
        :_name(name)
        ,_num(num)
    {}

protected:
string _name; // 姓名
int _num;
};
class Student : public Person
{
public:
Student(const char* name = "", const int num1 = 0, int num2 = 0)
:Person(name,num1)
,_num(num2)
{}
void Display()
{
cout << _num << endl;
cout <}
protected:
int _num; // 學(xué)號(hào)
};

int main()
{
Person a("boday",15);
Student b("crash",1502,17);
b.Display();

return 0;

}

**運(yùn)行結(jié)果:**
![這里寫(xiě)圖片描述](/upload/otherpic46/20180422193345134?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM4NjQ2NDcw/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
可以很明顯看出此時(shí)打印的是子類的成員,而隱藏掉了父類的成員,(```這就是隱藏```)

### 派生類的默認(rèn)成員函數(shù)
 在繼承關(guān)系里面,在派生類中如果沒(méi)有顯示定義這六個(gè)成員函數(shù),編譯系統(tǒng)則會(huì)默認(rèn)合成這六個(gè)默認(rèn)的成員函數(shù)。
![這里寫(xiě)圖片描述](/upload/otherpic46/20180421222558568?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM4NjQ2NDcw/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
**來(lái)個(gè)栗子說(shuō)說(shuō)默認(rèn)成員函數(shù)的前四個(gè)(` 后兩個(gè)不常用`)**
```cpp
class Person
{
public:
    Person(const char *name = "",int num = 0) //父類構(gòu)造函數(shù)
        :_name(name)
        ,_num(num)
    {}
    ~Person()//父類析構(gòu)函數(shù)
    {
        cout << "~Person()" << endl;
    }
    Person(const Person& p)//父類拷貝構(gòu)造函數(shù)
        :_name(p._name)
        ,_num(p._num)
    {}
    Person& operator=(const Person& p)//父類賦值運(yùn)算符重載
    {
        if (this != &p)
        {
            _name = p._name;
            _num = p._num;
        }
        return *this;
    }

protected:
    string _name; // 姓名
    int _num;
};
class Student : public Person
{
public:
    Student(const char* name = "", const int num1 = 0, int num2 = 0)//子類構(gòu)造函數(shù)
        :Person(name,num1)   
        ,_num(num2)
    {}
    ~Student()//子類析構(gòu)函數(shù)
    {
        cout << "~Student()" << endl;
    }
    Student(const Student& s)//子類拷貝構(gòu)造函數(shù)
        :Person(s)
        ,_num(s._num)
    {}
    Student& operator=(const Student& s)//子類賦值運(yùn)算符重載
    {
        Person::operator=(s); //顯示調(diào)用父類賦值運(yùn)算符重載
        _num = s._num;
    }
protected:
    int _num; // 學(xué)號(hào)
};

先調(diào)用父類構(gòu)造函數(shù),在調(diào)用基類構(gòu)造函數(shù);析構(gòu)函數(shù)調(diào)用順序與構(gòu)造函數(shù)相反(先構(gòu)造后析構(gòu),這個(gè)和棧的規(guī)則有關(guān)(先入后出))

繼承方式(單繼承,多繼承,菱形繼承)

C++中的繼承詳解

1.單繼承

定義:一個(gè)子類只有一個(gè)直接父類時(shí)稱這個(gè)繼承關(guān)系為單繼承
代碼示例:
class A
{
protected:
    int _a;
};

class B : public A //B類 繼承 A類
{
protected:
    int _b;
};

2.多繼承

定義:一個(gè)子類有兩個(gè)或以上直接父類時(shí)稱這個(gè)繼承關(guān)系為多繼承
代碼示例:
class A
{
protected:
    int _a;
};

class B 
{
protected:
    int _b;
};

class C : public A,B
{
protected:
    int _c;
};

3.菱形繼承

代碼示例:
class Person
{
public:
    string _name; // 姓名
};
class Student : public Person
{
protected:
    int _num; //學(xué)號(hào)
};
class Teacher : public Person
{
protected:
    int _id; // 職工編號(hào)
};
class Assistant : public Student, public Teacher
{
protected:
    string _majorCourse; // 主修課程
};
void Test()
{
    // 顯示指定訪問(wèn)哪個(gè)父類的成員(二義性問(wèn)題)
    Assistant a;
    a.Student::_name = "xxx";
    a.Teacher::_name = "yyy";//數(shù)據(jù)冗余問(wèn)題
}

很明顯菱形繼承存在問(wèn)題,存在二義性和數(shù)據(jù)冗余的問(wèn)題。為了解決這個(gè)問(wèn)題就引入了虛繼承。

虛繼承:解決菱形繼承的二義性和數(shù)據(jù)冗余的問(wèn)題

在聲明派生類時(shí),指定其繼承方式時(shí)聲明為虛繼承的方式。如

class A
{
public:
    int _a;
};

class B : virtual public A //聲明為虛基類
{
protected:
    int _b;
};

class C : virtual public A //聲明為虛基類
{
protected:
    int _c;
};

class D : public B,public C
{
protected:
    int _d;
};

看看測(cè)試效果:

void Test()
{
    D d;
    d._a = 10;
}

C++中的繼承詳解
是不是很疑惑到底是如何解決的?那就要深入到底層探索下
C++中的繼承詳解
這里在虛繼承時(shí)用一個(gè)虛基表存放偏移量,這樣B和C類同時(shí)使用一個(gè)虛基表存放A相對(duì)于B和C的偏移量,當(dāng)發(fā)生虛繼承時(shí)A會(huì)存放在一個(gè)公共區(qū)域,這就很好的解決了二義性問(wèn)題,同時(shí)也節(jié)省了空間。
虛繼承很好的解決了菱形繼承帶來(lái)的問(wèn)題。

這里建議大家寫(xiě)下代碼調(diào)試一下,同時(shí)查看內(nèi)存變化。


本文題目:C++中的繼承詳解
本文網(wǎng)址:http://weahome.cn/article/ipphhc.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部