In a larger code base I have encountered code like this (see on godbolt):
struct Foo {};
struct Base {
Foo* a;
};
struct Bar : public Base {
static Foo* Bar::*mybar[];
};
Foo* Bar::Bar::*mybar[] = {
&Base::a
};
To be honest, I'm baffled. This looks like it's initializing a static array of Foo
pointers in Bar
with a non-static member variable of Base
. How is that even possible without an object?
(Disclaimer: This is found in production code that actually works - hopefully not relying on UB?)
Also, is there any problem if I remove the qualified name lookup like here? I'd like to refactor the code and make it more readable. All these Bar::
s seem quite superfluous, but since I'm not feeling so comfortable with the code I'd rather understand the implications first.
Unlike normal pointers, class member pointers can be though of as an offset into the class, where they are telling you which member of an object they point to. So in your code, mybar
is an array of class member pointers. When you do
Foo *Bar::Bar::*mybar[] = {
&Base::a
};
you initialize the array with a pointer to the a
member of Base
. This isn't actually pointing to an a
, it just tells the compiler which member of the object to return if you access it with an object. That would look like
Base foo; // now we have an actual object
foo.*mybar[0]; // access the `a` member of `foo` by using the "offset"
How is that even possible without an object?
It is possible to create pointer to member variables without an object. The pointers can be used to dereference an actual member only in the presence of an object.
Simpler example:
struct Foo { int m; int n};
using MemberPtr = int Foo::*;
MemberPtr p1 = &Foo::m; // Instance of Foo is not needed.
MemberPtr p2 = &Foo::n; // Instance of Foo is not needed.
*p1 = 10; // Not allowed.
*p2 = 20; // Not allowed.
Foo a;
a.*p1 = 10; // Changes a.m
a.*p2 = 20; // Changes a.n
Foo b;
b.*p1 = 30; // Changes b.m
b.*p2 = 40; // Changes b.n
Please note that you are able to change values of members of two instances of the class using the same pointer to member variables.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With