1. 程式人生 > >父子間的沖突(四十)

父子間的沖突(四十)

C++ 父子沖突 作用域分辨符 同名成員函數

我們學習了繼承,那麽現在就有一個問題了:子類中是否可以定義父類中的同名成員呢?如果可以,那麽將如何區分?如果不可以,為什麽呢?我們來用代碼說明,看看是否支持

#include <iostream>
#include <string>

using namespace std;

class Parent
{
public:
    int mi;
};

class Child : public Parent
{
public:
    int mi;
};

int main()
{
    Child c;
    
    c.mi = 10;
    
    return 0;
}

我們在父類 Parent 中定義了一個成員變量 mi,在子類 Child 中也定義了成員變量 mi;那麽我們直接對 c.mi 進行賦值操作,看看編譯器能否識別?

技術分享圖片

經過編譯,我們知道了編譯器支持這樣的寫法,也就說,它知道此時我們賦值的是哪個 mi。在 C++ 中,其實子類是可以定義父類中的同名成員的,子類中的成員將隱藏父類中的同名成員。但父類中的同名成員依然存在於子類中,我們通過作用域分辨符(::)來訪問父類中的同名成員。下來我們通過編程來看看怎樣使用父類中被隱藏的同名成員。

#include <iostream>
#include <string>

using namespace std;

class Parent
{
public:
    int mi;
    
    Parent()
    {
        cout << "Parent(): &mi = " << &mi << endl;
    }
};

class Child : public Parent
{
public:
    int mi;
    
    Child()
    {
        cout << "Child(): &mi = " << &mi << endl;
    }
};

int main()
{
    Child c;
    
    c.mi = 10;
    c.Parent::mi = 100;
    
    cout << "c.mi = " << c.mi << endl;
    cout << "&c.mi = " << &c.mi << endl;
    
    cout << endl;
    
    cout << "c.Parent::mi = " << c.Parent::mi << endl;
    cout << "&c.Parent::mi = " << &c.Parent::mi << endl;
    
    return 0;
}

我們看到先打印兩個類中定義的變量的地址,然後進行賦值,通過再次打印賦值操作的變量的地址來確定我們操作的到底是父類中的成員變量還是子類中的成員變量,編譯結果如下

技術分享圖片

我們看到 c.mi 的地址和子類中的成變量的地址是一致的,而 c.Parent::mi 的地址和父類中的成員變量的地址是一致的。那麽類中的成員函數是否可以進行重載呢?重載函數的本質為多個不同的函數,函數名和參數列表是唯一的標識,函數重載必須發生在同一個作用域中。那麽子類中定義的函數是否能重載父類中的同名函數?我們還是以代碼為例來進行分析

#include <iostream>
#include <string>

using namespace std;

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

class Child : public Parent
{
public:
    int mi;
    
};

int main()
{
    Child c;
    
    c.mi = 10;
    c.Parent::mi = 100;
    
    cout << "c.mi = " << c.mi << endl;
    cout << "c.Parent::mi = " << c.Parent::mi << endl;
    
    c.add(1);
    c.add(2, 3);
    
    cout << endl;
    
    cout << "c.mi = " << c.mi << endl;
    cout << "c.Parent::mi = " << c.Parent::mi << endl;
    
    return 0;
}

我們在父類中定義了兩個 add 重載函數,那麽我們在 main 函數中去使用,看看它會用在父類還是子類的成員變量中。

技術分享圖片

我們看到是父類中的成員變量使用 add 函數了。那麽我們在子類中也定義 void add(int a, int b, int c) 函數呢?在 main 函數中添加 c.add(4, 5, 6);我們來看看編譯結果

技術分享圖片

它報錯了,沒有可調用的函數,因為在這會發生同名覆蓋。由此可見,子類中的函數無法重載父類中的成員函數,子類中的函數將隱藏父類中的同名函數。我們必須得使用作用域分辨符來訪問父類中的同名函數,那麽在子類中可以定義父類中完全相同的成員函數。我們試著加上作用分辨符(c.Parent::add(1); c.Parent::add(2, 3);),再來編譯下看看

技術分享圖片

我們看到已經編譯通過,並且運行也是我們想要的效果。通過對父子關系的學習,總結如下:1、子類中可以定義父類中的同名成員;2、子類中的成員將隱藏父類中的同名成員;3、子類和父類中的函數不能構成重載關系;4、子類可以定義父類中完全相同的成員函數;5、使用作用域分辨符可以訪問父類中的同名成員。


歡迎大家一起來學習 C++ 語言,可以加我QQ:243343083

父子間的沖突(四十)