Reputation: 24008
#include <iostream>
using namespace std;
template <typename E1, typename E2>
class Mix : public E1, public E2
{
public:
Mix() : E1(1), E2(2)
{
// Set nothing here
cerr << "This is " << this << " in Mix" << endl;
print(cerr);
}
void print(ostream& os)
{
os << "E1: " << E1::e1 << ", E2: " << E2::e2 << endl;
// os << "E1: " << e1 << ", E2: " << e2 << endl; won't compile
}
};
class Element1
{
public:
Element1(unsigned int e) : e1(e)
{
cerr << "This is " << this << " in Element1" << endl;
}
unsigned int e1;
};
class Element2
{
public:
Element2(unsigned int e) : e2(e)
{
cerr << "This is " << this << " in Element2" << endl;
}
unsigned int e2;
};
int main(int argc, char** argv)
{
Mix<Element1, Element2> m;
}
Now, since we're equally inheriting from the two template parameter classes, I would expect this
to be the same in the two constructors, but this is not the case. Here is the run log:
This is 0x7fff6c04aa70 in Element1
This is 0x7fff6c04aa74 in Element2
This is 0x7fff6c04aa70 in Mix
E1: 1, E2: 2
As you can see, while this
is the same in Element1 and Mix, this is not true for Element2. Why is that? Also, I would expect to have access to e1 and e2 from the base classes. Can you explain this behavior?
Upvotes: 1
Views: 93
Reputation: 2909
The Element Mix
contains an Element1
and an Element2
. These are - perhaps implementation specifically aligned - written after one another in memory. If you use Mix
as Element1
, this will point to the first of the two (with size of Element1
), if you use it as Element2
it will point to the second (with size of Element2
) and if you use it as Mix
it will point to the base address, which is the same as Element1
s base address, but has a differenz size (at least size of Element1
+ size of Element2
).
Edit: You can verify this by outputting the size too:
#include
using namespace std;
template <typename E1, typename E2>
class Mix : public E1, public E2
{
public:
Mix() : E1(1), E2(2)
{
// Set nothing here
cerr << "This is " << this << " + " << sizeof(*this) << " in Mix" << endl;
print(cerr);
}
void print(ostream& os)
{
os << "E1: " << E1::e1 << ", E2: " << E2::e2 << endl;
// os << "E1: " << e1 << ", E2: " << e2 << endl; won't compile
}
};
class Element1
{
public:
Element1(unsigned int e) : e1(e)
{
cerr << "This is " << this << " + " << sizeof(*this) << " in Element1" << endl;
}
unsigned int e1;
};
class Element2
{
public:
Element2(unsigned int e) : e2(e)
{
cerr << "This is " << this << " + " << sizeof(*this) << " in Element2" << endl;
}
unsigned int e2;
};
int main(int argc, char** argv)
{
Mix<Element1, Element2> m;
}
Output:
This is 0x7fffc9cad310 + 4 in Element1
This is 0x7fffc9cad314 + 4 in Element2
This is 0x7fffc9cad310 + 8 in Mix
E1: 1, E2: 2
Upvotes: 1