簡體   English   中英

為什么我不能將指向Derived類成員函數的指針強制轉換為類Base?

[英]why can't I cast a pointer to Derived class member function to the same but of class Base?

對我來說,將void(Derived::*)()轉換為void(Base::*)()看起來非常安全,就像在這段代碼中一樣:

#include <iostream>
#include <typeinfo>
using namespace std;
struct Base{
    void(Base::*any_method)();
    void call_it(){
        (this->*any_method)();
    }
};
struct Derived: public Base{
    void a_method(){
        cout<<"method!"<<endl;
    }
};
int main(){
    Base& a=*new Derived;
    a.any_method=&Derived::a_method;
    a.call_it();
}

但編譯器抱怨a.any_method=&Derived::a_method; 這是一個阻止細微編程錯誤的障礙,還是一些讓編譯器編寫者生活更輕松的東西? 是否存在變通方法讓Base類具有指向Derived成員函數的指針而沒有類型知識 (也就是說,我不能使Base成為模板參數Derived模板)。

如果您的Derived::a_method()嘗試使用僅存在於Derived而不是Base的數據成員,並且您在Base對象(或從Base Derived但與Derived無關的對象)上調用它,會發生什么?

相反的轉換是有道理的,這個沒有。

不,這有潛在危險。

派生類函數可以使用*this所有派生類屬性。 可以在任何基類實例上調用指向基類函數的指針,甚至是那些不是派生類型的實例。

訪問不是派生類的實例的派生類屬性是行不通的,因此正確地不允許將指向派生類函數的指針強制轉換為指向基類指針的指針。

另一方面,將指向基類函數的指針轉換為指向派生類函數的指針是安全且合法的。

您需要使用std::function<void()> 這可以是任何類的任何成員,lambda,自由函數,函數對象,無論你需要什么,這是非常方便的。

#include <iostream>
#include <typeinfo>
using namespace std;
struct Base{
    std::function<void()> any_method;
    void call_it(){
        any_method();
    }
};
struct Derived: public Base{
    void a_method(){
        cout<<"method!"<<endl;
    }
};
int main(){
    Derived* d = new Derived;
    Base& a= *d;
    a.any_method = [d] { d->a_method(); };
    a.call_it();
}

在這里你可以看到any_method的實際實現完全是從struct Base抽象出來的,我可以提供一個完成任何事情的函數對象 - 包括方便地調用Derived方法。

我想這可能有點令人驚訝。 但是,如果你考慮它,這是有道理的。

對於兩種類型之間的自動轉換,應該保持以下關系:第一種類型的任何實例都應該在第二種類型中表示。

例如,如果dDerived的實例,則它可以自動轉換為Base&因為Derived任何實例也是Base的實例。 這是繼承。

現在,當指向成員函數的指針時,關系實際上是相反的。 很明顯,任何Base方法都存在於Derived的實例中,但反之則不然。 畢竟,導出的全部內容是更頻繁地添加新功能。

另一種可視化方法是使用自由函數。 this只是常規函數中的隱式參數,如果我們將其顯式化,我們得到:

void Base@call_it(Base& self);

void Derived@a_method(Derived& self);

現在,如果我有兩個Derived類型的實例d和類型為Base b ,那么:

  • Base@call_it(d)是有道理的
  • Derived@a_method(b)是編譯錯誤

后者可以是Derived@a_method(dynamic_cast<Derived&>(b)) ,但這會引入運行時檢查以實際驗證屬性。 靜態地說它不是可判定的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM