about pointers on class' members

Discussion in 'C++' started by Chameleon, Dec 22, 2009.

  1. Chameleon

    Chameleon Guest

    We have this structure:
    -----------------------
    struct A {
    struct B {
    ...
    } b;

    ...

    struct C {
    void no_way_dude();
    } c;
    };
    -----------------------

    How can I have access on 'b' from inside of 'no_way_dude()'?
    I mean without pass parameters to 'C()' or to 'no_way_dude()'
    You can use 'friend' as you wish.

    Until now I use:
    B &b = *(B*)(((char*) this) - sizeof(B));
    But it is totally lame.
    If I add a definition between B and C, it will screwed.


    Basically I need something like:
    off_t rel = (char*) A::C - (char*) A::B;

    Any workaround without pass pointers to functions?
    Chameleon, Dec 22, 2009
    #1
    1. Advertising

  2. On Dec 22, 1:51 pm, Chameleon <> wrote:
    > We have this structure:
    > -----------------------
    > struct A {
    >         struct B {
    >         ...
    >         } b;
    >
    >         ...
    >
    >         struct C {
    >                 void no_way_dude();
    >         } c;};
    >
    > -----------------------
    >
    > How can I have access on 'b' from inside of 'no_way_dude()'?
    > I mean without pass parameters to 'C()' or to 'no_way_dude()'


    You can't since b and c are unrelated objects. The only relation
    is that both are members of A. So, the only way to reach one from
    the other is through an instance of A: a.b or a.c.

    Both B and C objects can exist as stand-alone objects:

    A::B A::GetB() const { return B(); }

    So there can not be a way to reach one from the other.
    Gert-Jan de Vos, Dec 22, 2009
    #2
    1. Advertising

  3. Chameleon

    Chameleon Guest

    στις 22 Δεκ 2009 15:32, O/H Gert-Jan de Vos έγÏαψε:
    > On Dec 22, 1:51 pm, Chameleon<> wrote:
    >> We have this structure:
    >> -----------------------
    >> struct A {
    >> struct B {
    >> ...
    >> } b;
    >>
    >> ...
    >>
    >> struct C {
    >> void no_way_dude();
    >> } c;};
    >>
    >> -----------------------
    >>
    >> How can I have access on 'b' from inside of 'no_way_dude()'?
    >> I mean without pass parameters to 'C()' or to 'no_way_dude()'

    >
    > You can't since b and c are unrelated objects. The only relation
    > is that both are members of A. So, the only way to reach one from
    > the other is through an instance of A: a.b or a.c.
    >
    > Both B and C objects can exist as stand-alone objects:
    >
    > A::B A::GetB() const { return B(); }
    >
    > So there can not be a way to reach one from the other.


    void A::C::no_way_dude()
    {
    A *a = 0;
    B &b = *(B*)(((char*) this) - (char*) &a->c - (char*) &a->b);
    // DONE!!!
    }
    Chameleon, Dec 22, 2009
    #3
  4. On 22 déc, 13:51, Chameleon <> wrote:
    > We have this structure:
    > -----------------------
    > struct A {
    >         struct B {
    >         ...
    >         } b;
    >
    >         ...
    >
    >         struct C {
    >                 void no_way_dude();
    >         } c;};
    >
    > -----------------------
    >
    > How can I have access on 'b' from inside of 'no_way_dude()'?
    > I mean without pass parameters to 'C()' or to 'no_way_dude()'
    > You can use 'friend' as you wish.
    >
    > Until now I use:
    > B &b = *(B*)(((char*) this) - sizeof(B));
    > But it is totally lame.
    > If I add a definition between B and C, it will screwed.
    >
    > Basically I need something like:
    > off_t rel = (char*) A::C - (char*) A::B;
    >
    > Any workaround without pass pointers to functions?


    There is a solution but it is not practical with the current standard,
    a little bit better with the next (I will explain latter): the trick
    is to use the offsetof() macro.

    struct A {
    struct B {
    ...
    } b;

    ...

    struct C {
    void no_way_dude()
    {
    B& my_b = owner().b;
    }
    private:
    A& owner() {
    return *reinterpret_cast<A*>(
    reinterpret_cast<char*>(this) -
    offsetof(A, c));
    }

    } c;
    };

    It has the drawback that it is not guaranteed by the current standard
    if A is not a POD and in the next standard if A is not a /standard
    layout/ class.

    Which means that
    - with the current standard, you have UB as soon as you define a
    constructor or private/public areas.
    - with the next standard, you have UB if you add virtual functions or
    virtual inheritance.

    Now in practice, compilers such as gcc and I think VC++ already
    support the offsetof() macro with a simple class (without virtual
    elements).

    It is a risky trick and you may be better without it.

    --
    Michael
    Michael Doubez, Dec 22, 2009
    #4
  5. Chameleon

    Jeff Flinn Guest

    Chameleon wrote:
    > στις 22 Δεκ 2009 15:32, O/H Gert-Jan de Vos έγÏαψε:
    >> On Dec 22, 1:51 pm, Chameleon<> wrote:
    >>> We have this structure:
    >>> -----------------------
    >>> struct A {
    >>> struct B {
    >>> ...
    >>> } b;
    >>>
    >>> ...
    >>>
    >>> struct C {
    >>> void no_way_dude();
    >>> } c;};
    >>>
    >>> -----------------------
    >>>
    >>> How can I have access on 'b' from inside of 'no_way_dude()'?
    >>> I mean without pass parameters to 'C()' or to 'no_way_dude()'

    >>
    >> You can't since b and c are unrelated objects. The only relation
    >> is that both are members of A. So, the only way to reach one from
    >> the other is through an instance of A: a.b or a.c.
    >>
    >> Both B and C objects can exist as stand-alone objects:
    >>
    >> A::B A::GetB() const { return B(); }
    >>
    >> So there can not be a way to reach one from the other.

    >
    > void A::C::no_way_dude()
    > {
    > A *a = 0;
    > B &b = *(B*)(((char*) this) - (char*) &a->c - (char*) &a->b);
    > // DONE!!!
    > }


    And what happens when you or someone else tries the following weeks,
    months or years later:

    int main()
    {
    A:C c;

    c.no_way_dude();

    return 0;
    }

    You basically have a (very) bad design.

    Jeff
    Jeff Flinn, Dec 22, 2009
    #5
  6. Vladimir Jovic, Dec 22, 2009
    #6
  7. On 22 déc, 16:01, Jeff Flinn <> wrote:
    > Chameleon wrote:
    > > στις 22 Δεκ 2009 15:32, O/H Gert-Jan de Vos έγÏαψε:
    > >> On Dec 22, 1:51 pm, Chameleon<>  wrote:
    > >>> We have this structure:
    > >>> -----------------------
    > >>> struct A {
    > >>>          struct B {
    > >>>          ...
    > >>>          } b;

    >
    > >>>          ...

    >
    > >>>          struct C {
    > >>>                  void no_way_dude();
    > >>>          } c;};

    >
    > >>> -----------------------

    >
    > >>> How can I have access on 'b' from inside of 'no_way_dude()'?
    > >>> I mean without pass parameters to 'C()' or to 'no_way_dude()'

    >
    > >> You can't since b and c are unrelated objects. The only relation
    > >> is that both are members of A. So, the only way to reach one from
    > >> the other is through an instance of A: a.b or a.c.

    >
    > >> Both B and C objects can exist as stand-alone objects:

    >
    > >> A::B A::GetB() const { return B(); }

    >
    > >> So there can not be a way to reach one from the other.

    >
    > > void A::C::no_way_dude()
    > > {
    > >     A *a = 0;
    > >     B &b = *(B*)(((char*) this) - (char*) &a->c - (char*) &a->b);
    > >     // DONE!!!
    > > }

    >
    > And what happens when you or someone else tries the following weeks,
    > months or years later:
    >
    > int main()
    > {
    >     A:C c;
    >
    >     c.no_way_dude();
    >
    >     return 0;
    >
    > }


    You can make C constructor protected and A become C's friend.

    > You basically have a (very) bad design.


    It could be convenient in some cases if the standard provided more
    tools to make it work.

    --
    Michael
    Michael Doubez, Dec 22, 2009
    #7
  8. Chameleon

    Jeff Flinn Guest

    Michael Doubez wrote:
    > On 22 déc, 16:01, Jeff Flinn <> wrote:
    >> Chameleon wrote:
    >>> στις 22 Δεκ 2009 15:32, O/H Gert-Jan de Vos έγÏαψε:
    >>>> On Dec 22, 1:51 pm, Chameleon<> wrote:
    >>>>> We have this structure:
    >>>>> -----------------------
    >>>>> struct A {
    >>>>> struct B {
    >>>>> ...
    >>>>> } b;
    >>>>> ...
    >>>>> struct C {
    >>>>> void no_way_dude();
    >>>>> } c;};
    >>>>> -----------------------
    >>>>> How can I have access on 'b' from inside of 'no_way_dude()'?
    >>>>> I mean without pass parameters to 'C()' or to 'no_way_dude()'
    >>>> You can't since b and c are unrelated objects. The only relation
    >>>> is that both are members of A. So, the only way to reach one from
    >>>> the other is through an instance of A: a.b or a.c.
    >>>> Both B and C objects can exist as stand-alone objects:
    >>>> A::B A::GetB() const { return B(); }
    >>>> So there can not be a way to reach one from the other.
    >>> void A::C::no_way_dude()
    >>> {
    >>> A *a = 0;
    >>> B &b = *(B*)(((char*) this) - (char*) &a->c - (char*) &a->b);
    >>> // DONE!!!
    >>> }

    >> And what happens when you or someone else tries the following weeks,
    >> months or years later:
    >>
    >> int main()
    >> {
    >> A:C c;
    >>
    >> c.no_way_dude();
    >>
    >> return 0;
    >>
    >> }

    >
    > You can make C constructor protected and A become C's friend.


    Or just fix the design.

    >> You basically have a (very) bad design.

    >
    > It could be convenient in some cases if the standard provided more
    > tools to make it work.


    In this case convenience makes for brittle code.

    Jeff
    Jeff Flinn, Dec 22, 2009
    #8
  9. Chameleon

    Chameleon Guest

    στις 22 Δεκ 2009 17:11, O/H Vladimir Jovic έγÏαψε:
    > Chameleon wrote:
    >
    > [snip]
    >> void A::C::no_way_dude()
    >> {
    >> A *a = 0;
    >> B &b = *(B*)(((char*) this) - (char*) &a->c - (char*) &a->b);
    >> // DONE!!!
    >> }

    >
    > Take a look at this:
    > http://www.google.de/#hl=en&source=...ereferencing null pointer&fp=4fc34adcbfaca52f
    >
    >
    >
    > Why don't you move the no_way_dude() method from C to A? Then instead of
    > passing objects of type C, pass objects of type A



    Yes, this is what I wrote before.

    But because A had many many members, I thought to group similar
    functions of A in subclasses.

    I realize that I am a little bit influenced from Java.
    In Java if a subclass is not static can have access to parent class.
    Chameleon, Dec 22, 2009
    #9
  10. Le 22/12/2009 18:04, Jeff Flinn a écrit :
    > Michael Doubez wrote:
    >> On 22 déc, 16:01, Jeff Flinn <> wrote:
    >>> Chameleon wrote:
    >>>> στις 22 Δεκ 2009 15:32, O/H Gert-Jan de Vos έγÏαψε:
    >>>>> On Dec 22, 1:51 pm, Chameleon<> wrote:
    >>>>>> We have this structure:
    >>>>>> -----------------------
    >>>>>> struct A {
    >>>>>> struct B {
    >>>>>> ...
    >>>>>> } b;
    >>>>>> ...
    >>>>>> struct C {
    >>>>>> void no_way_dude();
    >>>>>> } c;};
    >>>>>> -----------------------
    >>>>>> How can I have access on 'b' from inside of 'no_way_dude()'?
    >>>>>> I mean without pass parameters to 'C()' or to 'no_way_dude()'
    >>>>> You can't since b and c are unrelated objects. The only relation
    >>>>> is that both are members of A. So, the only way to reach one from
    >>>>> the other is through an instance of A: a.b or a.c.
    >>>>> Both B and C objects can exist as stand-alone objects:
    >>>>> A::B A::GetB() const { return B(); }
    >>>>> So there can not be a way to reach one from the other.
    >>>> void A::C::no_way_dude()
    >>>> {
    >>>> A *a = 0;
    >>>> B &b = *(B*)(((char*) this) - (char*) &a->c - (char*) &a->b);
    >>>> // DONE!!!
    >>>> }
    >>> And what happens when you or someone else tries the following weeks,
    >>> months or years later:
    >>>
    >>> int main()
    >>> {
    >>> A:C c;
    >>>
    >>> c.no_way_dude();
    >>>
    >>> return 0;
    >>>
    >>> }

    >>
    >> You can make C constructor protected and A become C's friend.

    >
    > Or just fix the design.


    Since I don't know the problem space of the OP, I could not say anything
    about the design. What he is trying to do is a pattern I know under the
    name of 'memberspace':
    http://accu.org/index.php/journals/1527

    And if it fits his needs, he can simply put a comment in the code such as:
    \warning this class is intended to be used in class A and nowhere else.

    Because, of course, one reads the doc in the header before using a class :)

    >>> You basically have a (very) bad design.

    >>
    >> It could be convenient in some cases if the standard provided more
    >> tools to make it work.

    >
    > In this case convenience makes for brittle code.


    It is certainly not something I would do on a daily basis but I don't
    see where the robustness is impacted. In a well designed code, the
    no_way_dude() would be the only responsibility of class C and there
    would be no incentive to reuse it outside A.

    --
    Michael
    Michael DOUBEZ, Dec 22, 2009
    #10
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Robert Dormer

    pointers to members inside a class?

    Robert Dormer, Sep 21, 2003, in forum: C++
    Replies:
    6
    Views:
    347
    Mike Wahler
    Sep 22, 2003
  2. CoolPint
    Replies:
    8
    Views:
    957
    Jeff Schwab
    Dec 14, 2003
  3. Oystein Haare

    Class members, pointers or not?

    Oystein Haare, Apr 28, 2004, in forum: C++
    Replies:
    4
    Views:
    366
    Dave Moore
    Apr 29, 2004
  4. hdixon
    Replies:
    3
    Views:
    628
    hdixon
    Jul 9, 2006
  5. cerr

    pointers, pointers, pointers...

    cerr, Apr 7, 2011, in forum: C Programming
    Replies:
    12
    Views:
    657
Loading...

Share This Page