2011-01-27 2 views
1

Следующий код из here:Base-из-членами Idiom в C++

#include <streambuf> // for std::streambuf 
#include <ostream> // for std::ostream 

class fdoutbuf 
    : public std::streambuf 
{ 
public: 
    explicit fdoutbuf(int fd); 
    //... 
}; 

class fdostream 
    : public std::ostream 
{ 
protected: 
    fdoutbuf buf; 
public: 
    explicit fdostream(int fd) 
     : buf(fd), std::ostream(&buf) // This is not allowed. 
              // buf can't be initialized before std::ostream. 
     {} 
    //... 
}; 

Я не очень понимаю, комментарий. Почему «buf не может быть инициализирован до std :: ostream»? Могу ли я использовать некоторую помощь, чтобы понять это?

+0

Фактически этот код полностью в порядке, если конструктор базового класса (в этом случае 'std :: ostream (std :: streambuf * buf_ptr)' не получает доступ к объекту buf (aka '* buf_ptr)'. ' & buf' правильно указывает на адрес памяти, где 'buf' будет построен позже, так как указатель' this' уже действителен в списке инициаторов-членов. – smerlin

ответ

6

Порядок инициализации определяется порядком объявления ваших членов класса, а унаследованные классы - перед всем этим. Возьмем простой пример, иллюстрирующий основную проблему, не обращаясь к наследованию:

class C 
{ 
    int a, b; 
public: 
    C() : b(1), a(b) {} // a is initialized before b! 
}; 

код не делать то, что вы думаете! a сначала инициализируется, затем b инициализируется одним. Так что это зависит от того, деклараций не порядок в списке инициализации:

int a, b; 

Теперь та же идея относится к базовым классам, которые инициализированы перед производными членами класса. Чтобы решить эту проблему, вы создаете класс, который вам присущ, который содержит член, который вы хотите инициализировать из базового класса. Разумеется, этот класс-помощник должен быть до того, который вы на самом деле получаете.

+0

Хорошее объяснение! – Nawaz

3

Вы должны вызвать конструктор базового класса, прежде чем инициализировать переменные-члены, но вы передадите этому конструктору указатель на buf (переменную-член, которая не определена в этой точке).

+0

Ох ... дерьмо .. такая основная вещь, которую я забыл : – Nawaz

+0

его «указатель на переменную-член», а не «переменная-член», что имеет большое значение. См. Мой комментарий выше. «Сначала вы должны вызвать конструктор базового класса», это неправильно, поскольку не вы но язык делает это. – smerlin

+0

Спасибо, я исправил эту вещь указателем. Bur Я думаю, что ваш второй пункт - это всего лишь формулировка, потому что вы все равно должны поместить вызов (или, тем не менее, его имя) в конструктор там (потому что это надеется параметр), и я бы подумал, что код неправильный, если он был помещен в неправильном порядке, даже если он будет технически корректным - читаемость является ключевой :-) – thbusch