搜尋

首頁  >  問答  >  主體

c++多态性测试代码中遇到了类型限定符不兼容


编程菜鸟,在学习c++多态性的过程中,写了这样的测试代码,这里会有类型限定符不兼容。
当我在抽象基类的函数声明后添加上const后,就不会出现类型不兼容,这是为什么?

PHP中文网PHP中文网2886 天前473

全部回覆(3)我來回復

  • PHP中文网

    PHP中文网2017-04-17 13:22:14

    const限定的變數以及其引用只能呼叫const限定的成員函數
    const限定代表變數的值不會改變,而要想不改變變數的值則只能呼叫const修飾的成員函數

    回覆
    0
  • 高洛峰

    高洛峰2017-04-17 13:22:14

    你的問題其實與多態無關,要解答你這個問題需要兩個方面的知識點。

    1. 成員函數的this指標

    首先,類別的成員函數內要存取類別的成員,需要透過this指標存取(名稱不衝突時可省略),透過一個物件呼叫成員函數的時候會將物件本身透過this指標傳遞給成員函數。例如:

    class A {
    public:
        explicit A(int xx = 0) : x(xx) {}
        int get() { return x; }
        void set(int xx) { x = xx; }
    private:
        int x;
    };
    
    int main() {
        A a;
        a.set(10);  // a.x = 10
        int i = a.get();  // i = 10
    }

    為什麼我能在a.get()函數裡存取物件a的成員x?就是透過這個this指針。在透過a呼叫a.get()的時候,編譯器會把物件a的位址賦值給this指針,這裡的this指標的型別是A *const。而在get()函數內,return x;這個語句其實相當於return this->x;,這樣我們就能夠透過a.get()來存取物件a的成員x了。

    同理,為什麼a.set(10);能夠把物件a的成員x賦值成10?也是透過this指針。 x = xx;就相當於this->x = xx;

    以上兩種情況下,由於x的解析不可能出現歧義,所以this指標可以省略。但是,如果我想在成員函數set的參數裡使用與成員x相同的變數名稱該怎麼辦?依然透過this指針進行區分。我們可以把成員函數set的定義修改如下:

    A::void set(int x) { this->x = x; }

    這裡的this指標就不能省略了,否則的話,寫成x = x;就會出現歧義,編譯器無法解析x到底是函數的參數還是物件的成員。

    2. const成員函數

    考慮一個情況,在前面的例子中,我們的對象a是一個非常量對象,如果我們想使用類別A聲明一個常數對象怎麼辦?例如

    int main() {
        const int ci = 10;
        int i = ci;
        const A ca(5);  // ca.x = 5
        int j = ca.get();  // 编译错误
    }

    對於內建類型,可以直接定義常數ci,並且使用它的值。那對於我們自己定義的類別A,我們也可以用相同的方法定義常數ca,透過ca.get()取得物件a的成員x的值。

    但是,在使用成員函數取得它的資料成員x的值的時候,我們實際上仍然透過this指標來存取成員x,問題是,此時this指標不是const A *const型,而是A *const類型。我們知道,不可以透過非常量的指標來存取常數的內容,即

    const int ci = 5;
    int *p = &ci;         // 错误
    const int *cp = &ci;  // 正确

    那麼如何透過this指標來存取成員x呢?我們需要想個辦法讓this指標變成const A *const型。辦法就是,在類別的成員函數宣告末尾加上const關鍵字,這樣就表示該成員函數是 const成員函數,而函數內this指標是常數型別。舉例來說,我們可以重載get()方法:

    int A::get() const { return x; }

    此時,

    int j = ca.get();  // j = 5

    就會正常運作了。

    應用

    具體到你的問題來說,

    當我在抽象基底類別的函數宣告後面加上const後,就不會出現型別不相容,這是為什麼?

    store_file()函數內,其參數img_file是一個常數參考類型,想要透過一個常數物件呼叫成員函數,就需要這個物件的成員函數的this指標也是常數型別。

    當你在抽象基底類別的get_file_name()函數宣告後面加上const以後,這個函數內的this指標就從Image_file *const型別變成了const Image_file *const型,此時return file_name + std::string(".gif");裡的成員file_name是透過常數類型的this指標呼叫的。從而滿足了上述要求。

    回覆
    0
  • PHP中文网

    PHP中文网2017-04-17 13:22:14

    const物件只能呼叫const成員函數

    回覆
    0
  • 取消回覆