2013-07-11 2 views
1
#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; 
} 

Теперь, поскольку мы одинаково наследуем от двух классов параметров шаблона, я ожидал бы, что this будет одинаковым в двух конструкторах, но это не тот случай. Вот журнал работы:Странность с множественным наследованием от двух параметров шаблона?

This is 0x7fff6c04aa70 in Element1 
This is 0x7fff6c04aa74 in Element2 
This is 0x7fff6c04aa70 in Mix 
E1: 1, E2: 2 

Как вы можете видеть, в то время как this то же самое в element1 и Mix, это не верно для ELEMENT2. Почему это? Кроме того, я ожидал бы получить доступ к e1 и e2 из базовых классов. Можете ли вы объяснить это поведение?

+2

Почему element1 и ELEMENT2 должны иметь один и тот же adrress? они не являются одним и тем же объектом. – PlasmaHH

+0

Кроме того, вы можете получить доступ к 'e1' и' e2' из базового класса, просто добавьте 'this->' перед ними. Посмотрите [здесь] (http://stackoverflow.com/questions/3799495/template-inheritance-c). – soon

+0

@ спасибо, я знал об этом, но временно забыл. :) – tunnuz

ответ

1

Элемент Mix содержит Element1 и Element2. Это - возможно реализация, специально выровненная - написанная друг за другом в памяти. Если вы используете Mix как Element1, это будет указывать на первое из двух (с размером Element1), если вы используете его как Element2, оно будет указывать на второе (с размером Element2), и если вы используете его как Mix, он будет укажите на базовый адрес, который совпадает с базовым адресом Element1 s, но имеет разный размер (не менее Element1 + размер Element2).

Edit: Вы можете проверить это, выводя размер тоже:

#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; 
} 

Выход:

This is 0x7fffc9cad310 + 4 in Element1 
This is 0x7fffc9cad314 + 4 in Element2 
This is 0x7fffc9cad310 + 8 in Mix 
E1: 1, E2: 2 
Смежные вопросы