Указатель на атрибут указателя - PullRequest
3 голосов
/ 16 декабря 2010

Есть ли способ смоделировать эту ситуацию в C ++?

У меня есть два объекта A и B, каждый из которых имеет один атрибут, например, int i;Также у меня есть один указатель po, указывающий на объект, и один указатель pi, указывающий на целое число.Я хочу иметь целочисленный указатель, указывающий на атрибут в текущем объекте, на который указывает указатель.Что-то вроде:

po = A;
pi = po->i;
// pi points to A.i
po = B;
// now pi points to B.i

Я почти уверен, что это не может быть достигнуто с помощью указателей, но я хочу знать, есть ли какой-нибудь способ сделать это.

Ответы [ 8 ]

4 голосов
/ 16 декабря 2010

То, что вы ищете, называется «указатели на участников». Предположим, что A и B имеют тип T, тогда вы можете написать:

struct T { int i; };
T A, B, C; // some objects of this type

int T::*pi = &T::i; // pi is a pointer to an int member of T

T* po;
po = &A;
cout << po->*pi << '\n'; // prints A.i
po = &B;
cout << po->*pi << '\n'; // prints B.i

cout << C.*pi << '\n'; // prints C.i
2 голосов
/ 16 декабря 2010
struct O
{
    int i;
};

struct P
{
    void operator=(O & rhs)
    {
        po = &rhs;
        pi = &rhs.i;
    }

    O * po;
    int * pi;
};

int main()
{
    P po;
    int *& pi = po.pi;

    O A,B;
    A.i = 7;
    B.i = 19;

    po = A;
    cout << *pi << endl;
    po = B;   
    cout << *pi << endl;
}
2 голосов
/ 16 декабря 2010

На самом деле вы не можете сделать это прямо вперед.pi должен быть уведомлен / изменен, если po изменится.С pi, являющимся объектом нового типа AutoReference, вы могли бы достичь этого, но никто не поймет код.Я имею в виду «не прямо»: следующие работы работают, но не делают.

class AutoReference
{
public:
  AutoReference( ClassA ** ppObj )
  : mppObj( ppObj )
  {
  }

  ClassA * operator->()
  {
    return *mppObj;
  }

private:
  ClassA ** mppObj;
};


po = A;
AutoReference pi( &po );
// pi "points" to A.i
po = B;
// now pi "points" to B.i
1 голос
/ 16 декабря 2010

Или вы можете просто сделать указатель на указатель, если это лучше подходит вашей ситуации.

T a, b;
a.i = 6;
b.i = 9;

T* po = &a;
T** pi = &po;
std::cout << (*pi)->i;  // Prints 6

po = &b;
std::cout << (*pi)->i;  // Prints 9
0 голосов
/ 16 декабря 2010

Это будет работать, но я нахожу это некрасивым .

class MyObject
{
public:
 int m_i;

};

class AutomaticPointerToMember
{
    public:
 AutomaticPointerToMember(MyObject& obj,int MyObject::*):
 m_Object(obj),
 m_pInt(NULL)
 {}

    operator int* ()
 {
  return &(m_Object.*m_pInt);
 }

 int operator* ()
 {
  return (m_Object.*m_pInt);
 }

private:
 MyObject& m_Object;
 int MyObject::* m_pInt;
};

void test()
{
 MyObject a;
 MyObject b;

 MyObject * pObj =  &a;
 AutomaticPointerToMember pi(*pObj, &MyObject::m_i);

 int * pIa = pi; // pIa  points to a.i
    int ia = *pi; // value a.i

 pObj = &b; // pObj now points to b

 int * pIb = pi; // pIb  points to b.i

    int ib = *pi; // value b.i
}

и нужно будет также определить оператор &, * & и т. Д., Чтобы определить политкорректный интеллектуальный указатель ...

0 голосов
/ 16 декабря 2010

Короче говоря, это нельзя сделать так, как вы указали. И вы бы действительно этого не хотели.

Представьте себе хаос, который может обрушиться на ваше приложение, если изменение одной переменной также приведет к изменению других совершенно разных переменных. Это было бы как собаки и кошки, живущие вместе. Массовая истерия.

Но также мало смысла делать именно то, о чем вы просили, и это заставляет меня думать, что то, что вы действительно после, - это нечто совершенно другое. Например, в приведенном выше примере было бы гораздо проще сделать это:

po = A;
int ai = po->i;
po = B;
int ab = po->i;

Итак, что вы действительно пытаетесь сделать?

0 голосов
/ 16 декабря 2010

Как вы написали это:

pi продолжает указывать на A.i, когда po указывает на B.

Что не так с использованием

po = &A;
// do stuff using po and po->i (A and A.i)

po = &B;
// do stuff using po and po->i (B and B.i)
0 голосов
/ 16 декабря 2010
struct S {
   int i;
};


S a, b;
A * ap = & a;
int * ip = &(ap->i);

ip теперь указывает на члена a's i (обратите внимание, что они не называются атрибутами в земле C ++)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...