Question

In C++, it is small sample code that using std::enable_shared_from_this and inheritance. The p in this code, call a member function fb and fa. The p is the same object, but called fa and fb take a different this address.

Why take a different address?

code:

#include <memory>
#include <iostream>

template<class T> using S = std::enable_shared_from_this<T>;

struct A: S<A>    { auto fa() const -> void { std::cerr << this << "\n";} };
struct B: S<B>, A { auto fb() const -> void { std::cerr << this << "\n";} };

auto main() -> int
{
    auto p = std::make_shared<B>();

    p -> fa();
    p -> fb();

    std::cerr << p << "\n";
}

result: (tested compilers are clang++-3.2, g++-4.8 and em++-1.12 on Linux Mint 16 KDE and clang++-3.4 in wandbox as a online compiling platform.)

0x8376a8
0x837698
0x837698

wandbox: http://melpon.org/wandbox/permlink/rmcCrR0rqLd7tKfV

Was it helpful?

Solution

This has nothing to do with std::enable_shared_from_this; it's the general scenario of multiple inheritance. Inside a member function of class X, the type of this is X*, i.e. it points to the X subobject of the complete object. So when calling A::fa() on a B object, this refers to the A subobject of B. That can be offset from the object's initial address, based on the compiler's chosen memory layout.

In other words, an object B contains both a base class object A and a base class object S<B>. Since you listed S<B> first, the compiler chose to lay out S<B> first in B's layout, and A after it. So the memory layout looks something like this:

+-------+-----+---------------------------+
| S<B>  | A   | B's non-inherited members |
+-------+-----+---------------------------+
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top