Прохладная вещь с С++ заключается в том, что она позволяет создавать переменные типов-указателей. Наиболее распространенным случаем использования является получение указателя на метод:
struct foo
{
int x() { return 5; }
};
int (foo::*ptr)() = &foo::x;
foo myFoo;
cout << (myFoo.*ptr)() << '\n'; // prints "5"
Однако, возившись, я понял, что они могут точно также указывать на переменные-члены:
struct foo
{
int y;
};
int foo::*ptr = &foo::y;
foo myFoo;
myFoo.*ptr = 5;
cout << myFoo.y << '\n'; // prints "5"
Это довольно рад. Это привело меня к дальнейшему эксперименту: что, если вы могли бы получить указатель на под-член структуры?
struct foo
{
int y;
};
struct bar
{
foo aFoo;
};
int bar::*foo::*ptr;
Этот фактически компилируется.
Однако я понятия не имею, как назначить ему что-нибудь полезное. Ни одна из следующих работ:
int bar::*foo::*ptr = &bar::foo::y; // no member named "foo" in "bar"
int bar::*foo::*ptr = &bar::aFoo::y; // no member named "aFoo" in "bar" (??)
int bar::*foo::*ptr = &foo::y; // can't init 'int bar::*foo::*' with 'int foo::*'
Кроме того, в соответствии с ошибкой, которую это порождает, кажется, что этот тип не совсем то, что я имею в виду:
int bar::*foo::*ptr = nullptr;
bar myBar;
myBar.*ptr = 4; // pointer to member type ‘int bar::*’ incompatible
// with object type ‘bar’
Похоже, что это понятие уклоняется от меня. Очевидно, я не могу исключить, что он просто анализируется совершенно иначе, чем я ожидал.
Может кто-нибудь объяснить мне, что такое int bar::*foo::*
на самом деле? Почему gcc говорит мне, что указатель на член bar
несовместим с объектом bar
? Как я могу использовать int bar::*foo::*
, и как я могу построить допустимый?