簡體   English   中英

“指向成員的派生指針”到“指向成員的基指針”錯誤

[英]"Derived pointer to member" to "base pointer to member" error

為了支持一些編譯時魔法,我想使用指向成員的指針,例如:

struct BaseT
{
};

struct DerivedT: public BaseT
{
};

struct TestT 
{
    DerivedT testMem;

    typedef BaseT (TestT::* TestTMemPtr);

    constexpr TestT() = default;

    static constexpr TestTMemPtr testMemOffset()
    {
        return &TestT::testMem;
    }
};

int main()
{
    constexpr TestT test;
}

我不能將指向派生成員的指針作為指向基成員的指針返回,我用 clang 得到了這個:

cannot initialize return object of type 'TestT::TestTMemPtr' (aka 'BaseT (TestT::*)') with an rvalue of type 'DerivedT TestT::*'

我用gcc檢查了它:

error: invalid conversion from 'DerivedT TestT::*' to 'TestT::TestTMemPtr' {aka 'BaseT TestT::*'}

這是正常行為嗎? 我以為我總是可以使用派生指針作為基指針。

更新:好的,原來的例子不是最好的,我認為這個更具表現力,所以DerivedT*可以用作BaseT* ,但DerivedT TestT::*不能用作BaseT TestT::*

struct BaseT
{
};

struct DerivedT: public BaseT
{
};

struct TestT 
{
    DerivedT m_test;
};

using BaseTMemPtr = BaseT TestT::*;

int main()
{
    TestT test;
    BaseT* simplePtr = &test.m_test; //It is DerivedT*, but can be used as BaseT*
    BaseT (TestT::*memPtr) = &TestT::m_test; //Error, BaseT TestT::* cannot be used as DerivedT TestT::*
    BaseTMemPtr memPtr2 = &TestT::m_test; //Error, just the same
}

從繼承的角度來看, BaseT TestT::*DerivedT TestT::*是兩個不相關的類型¹,所以不能從后者初始化前者,反之亦然,就像不能用初始化int* a double*因為intdouble不是基於類和派生類。


¹ 我的意思是這些類型的兩個對象不指向兩個類,它們是另一個類的基礎。 BaseT TestT::*DerivedT TestT::*都是指針類型,但它們不指向兩個類,其中一個是另一個的基類; 它們甚至不首先指向類(參見下面的演示代碼),因此指向的類型之間不能有繼承關系,因為繼承是之間的事情,而不是一般類型之間的事情,例如成員函數類型。

#include <type_traits>
struct BaseT { };

struct DerivedT: public BaseT { };

struct TestT { };

template<typename T, typename = void>
struct points_to_class : std::false_type {};
template<typename T>
struct points_to_class<T*> : std::is_class<T> {};

static_assert(points_to_class<BaseT*>::value); // passes
static_assert(points_to_class<BaseT TestT::*>::value); // fails

但是,只有當它們都指向類並且這兩個類通過繼承相關時才可能進行指針之間的轉換嗎?

好吧,如果您查看cppreference.com上的Pointer 聲明頁面,它確實有一個關於Pointers to member functions 的部分,它是關於指向成員函數的指針之間的轉換。

但它是關於指向基類成員函數指針指向派生類的同一成員函數指針,而您似乎在尋找將指向成員函數( TestT指針轉換為返回基類( BaseT指向返回派生類 ( DerivedT )的同一類 ( TestT ) 的成員函數指針 同樣,這兩種類型是無關的。

暫無
暫無

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

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