代码之家  ›  专栏  ›  技术社区  ›  Sergej Andrejev

将指针类型派生到非指针类成员

c++
  •  1
  • Sergej Andrejev  · 技术社区  · 14 年前

    在由Rob McGregor命名的“使用C++”的书中,使用指针指向成员运算符的例子如下

    class mycls
    {
    public:
        int member;
        int *ptr;
    };
    
    void main()
    {
        mycls MyClass;
    
        // Derive a pointer type to the non-pointer class member
        int mycls::*member = &mycls::member;
    
        MyClass.ptr = new int;
        mycls* pMyClass = &MyClass;
    
        pMyClass->*member = 5;
        *MyClass.ptr = 10;
    
        cout << "pMyClass->*member = " << pMyClass->*member << "\n"; // pMyClass->*member = 5
        cout << "MyClass.*member = " << MyClass.*member << "\n"; // MyClass.*member = 5
        cout << "*MyClass.ptr = " << *MyClass.ptr << "\n"; // *MyClass.ptr = 10
        cout << "*pMyClass->ptr = " << *pMyClass->ptr << "\n"; // *pMyClass->ptr = 10
    
        delete MyClass.ptr;
    }
    

    在这个例子中,我不理解为什么成员变量 mycls::member 在(猜测)这行代码后,可能变成一个指针:

    int mycls::*member = &mycls::member; 
    

    这是干什么的?

    3 回复  |  直到 14 年前
        1
  •  6
  •   Daniel Earwicker    14 年前

    假设您有一个局部变量:

    int member;
    

    您可以使用以下方法创建指向它的指针:

    int *ptr = &member;
    

    为了获得指向成员语法的指针,我们只需追加 mycls:: 在适当的地方:

    int mycls::*member = &mycls::member;
    

    通过一个示例可以更清楚地看到指针如何在类型正确的类的任何成员之间进行切换:

    class C
    {
    public:
        int a;
        int b;
    };
    
    void main()
    {
        // make pointer to member, initially pointing to a
        int C::*ptrToMember = &C::a;
    
        C x;
        C *ptrToObj = &x; // make pointer to object x
    
        ptrToObj->*ptrToMember = 2; // store in a;
    
        ptrToMember = &C::b; // change pointer to b
    
        ptrToObj->*ptrToMember = 3; // store in b;
    }
    

    注意我们如何创建指向成员的指针 a 在我们创建类型的对象之前 C . 它只是指向成员的指针,而不是指向特定对象成员的指针。在“存储”步骤中,我们必须说出哪个对象以及哪个成员。

    更新

    在评论中,OP询问是否相同:

    int *ptr = &(ptrToObj->a);
    

    不,不是。这是指向任何 int ,内存中的任何位置。

    要理解这一点,最简单的方法就是从技术上考虑它的含义。“指针”是指 绝对的 在内存中的位置:查找对象的位置。“指向成员的指针”是 相对的 位置,有时称为偏移:在哪里找到对象 在内部 外部物体的储存。在内部,它们只是数字。必须将指向成员的指针添加到普通指针中,才能创建另一个指针。

    所以如果你有一个指向一个对象的指针 int 是一个对象!),您可以使用它更改存储在内存中该绝对位置的内容:

    *ptr = 123;
    

    但是,如果您有一个指向成员的指针,它就不是内存位置。它是一个偏移量,是要添加到内存位置的量。你不能单独使用它。必须将其“添加”到对象指针:

    ptrToObj->*ptrToMember = 132;
    

    这意味着:转到内存中的位置 ptrToObj ,然后按距离移动 ptrToMember .

        2
  •  2
  •   Bill    14 年前

    他给班上的成员打电话 member 以及指向成员的指针 成员 ,混淆了问题。像这样重命名它们有帮助吗?

    班级:

    class SampleClass
    {
    public:
        int m_data;
        int* m_pointer;
    };
    

    用途:

    int main()
    {
        SampleClass sample;
    
        // Derive a pointer type to the non-pointer class member
        int SampleClass::*pointerToMember = &SampleClass::m_data;
    
        sample.m_pointer = new int;
        SampleClass* pSample = &sample;
    
        pSample->*pointerToMember = 5;
        *sample.m_pointer = 10;
    
        // pSample->*pointerToMember = 5
        cout << "pSample->*pointerToMember = "
             << pSample->*pointerToMember << "\n";
    
        // sample.*pointerToMember = 5
        cout << "sample.*pointerToMember = "
             << sample.*pointerToMember << "\n";
    
        // *sample.m_pointer = 10
        cout << "*sample.m_pointer = "
             << *sample.m_pointer << "\n";
    
        // *pSample->m_pointer = 10
        cout << "*pSample->m_pointer = "
             << *pSample->m_pointer << "\n";
    
        delete sample.m_pointer;
    }
    

    [Code]

    编辑:回复“我仍然是咖喱是否 int *ptr = &(ptrToObj->a); 与使用指向书籍“”中的成员的指针相同:

    它不是指向成员的指针。它只是一个指向内存的普通指针,而内存恰好位于一个对象中。

    您可以在这里看到使用的语法:

    班级:

    class C
    {
    public:
        int a;
        int b;
    };
    

    用途:

    int main()
    {
        // make pointer to member, initially pointing to a
        int C::*ptrToMember = &C::a;
    
        C x = {10, 11};
        C *ptrToObj = &x; // make pointer to object x
    
        cout << "a initial value: " << ptrToObj->*ptrToMember << endl;
    
        ptrToObj->*ptrToMember = 2; // store in a;
    
        cout << "a after change: " << ptrToObj->*ptrToMember << endl;
    
        ptrToMember = &C::b; // change pointer to b
    
        cout << "b initial value: " << ptrToObj->*ptrToMember << endl;
    
        ptrToObj->*ptrToMember = 3; // store in b;
    
        cout << "b after change: " << ptrToObj->*ptrToMember << endl;
    
    
        int* ptr = &(ptrToObj->a);
        cout << "ptr to a: " << *ptr << endl;
    
        ptr = &(ptrToObj->b);
        cout << "ptr to b: " << *ptr << endl;
    }
    

    [Code]

        3
  •  0
  •   JoeG    14 年前

    声明中的星号字符是类型的一部分。

    你的声明分为

    Type: int mycls::*

    变量名: member

    Initialiser: = &mycls::member

    这个新变量 成员 Points是指向保存在 mycls . 它不必指向 mycls::member .