2013-04-16 2 views
2

Следующий код относится к обработке исключений. Автор попытался сказать нам, что, создавая все объекты, мы можем предотвратить утечку ресурсов. Мой вопрос: Почему конструкторы «cat» и «dog» называются раньше, чем конструктор «useresources»?Какой конструктор называется первым

//: C07:Wrapped.cpp 
// Safe, atomic pointers 
#include <fstream> 
#include <cstdlib> 
using namespace std; 
ofstream out("wrapped.out"); 
// Simplified. Yours may have other arguments. 
template<class T, int sz = 1> class PWrap { 
    T* ptr; 
public: 
    class RangeError {}; // Exception class 
    PWrap() { 
     ptr = new T[sz]; 
     out << "PWrap constructor" << endl; 
    } 
    ~PWrap() { 
     delete []ptr; 
     out << "PWrap destructor" << endl; 
    } 
    T& operator[](int i) throw(RangeError) { 
     if(i >= 0 && i < sz) return ptr[i]; 
     throw RangeError(); 
    } 
}; 
class Cat { 
public: 
    Cat() { out << "Cat()" << endl; } 
    ~Cat() { out << "~Cat()" << endl; } 
    void g() {} 
}; 
class Dog { 
public: 
    void* operator new[](size_t sz) { 
     out << "allocating an Dog" << endl; 
     throw int(47); 
    } 
    void operator delete[](void* p) { 
     out << "deallocating an Dog" << endl; 
     ::delete p; 
    } 
}; 
class UseResources { 
    PWrap<Cat, 3> Bonk; 
    PWrap<Dog> Og; 
public: 
    UseResources() : Bonk(), Og() { 
     out << "UseResources()" << endl; 
    } 
    ~UseResources() { 
     out << "~UseResources()" << endl; 
    } 
    void f() { Bonk[1].g(); } 
}; 
int main() { 
    try { 
     UseResources ur; 
    } catch(int) { 
     out << "inside handler" << endl; 
    } catch(...) { 
    out << "inside catch(...)" << endl; 
    } 
} ///:~ 
+3

Это не так. Но они вызываются до 'out <<" UseResources() "<< endl;'. Когда вы вводите тело своего конструктора, все объекты-члены будут иметь свои конструкторы. – john

ответ

3

Почему конструкторы «кошки» и «собаки» называют раньше, чем конструктор «useresources»?

Их называют раньше, чем тело из конструктора UseResources вводится.

UseResources имеет два элемента данных, которые являются экземплярами шаблона класса PWrap<>. Конструктор PWrap<T> конкретизирует ряд объектов типа T:

ptr = new T[sz]; 

Таким образом, в результате соответствующего числа вызова конструктора T (Cat или Dog, в вашем случае).

Поскольку ваши PWrap объекты являются членами данных о UseResources, их конструктор запускается на выполнение, прежде чем тело UseResources конструктора вводится. Так работает строительство объектов на C++.

Обоснование этого, чтобы убедиться, что, когда тело конструктора вводится, конструктор всех подобъектов (в том числе как базовых подобъектов и члена подобъектов - такие, как Bonk и Og) был завершен.

Таким образом, конструктор может полагаться на использование действительных подобъектов, чей инвариант класса уже установлен к моменту его выполнения.

Это, как пункт 12.6.2/10 C++ 11 Стандарт на описывает процесс:

В не делегировании конструктор, инициализация происходит в следующем порядке:

- Первый , и только для конструктора самого производного класса (1.8) виртуальные базовые классы инициализируются в порядком, который они появляются при первом обратном направлении слева направо по направленному ациклическому графу базовых классов, , где «left -to-right "- порядок появления базовых классов в базовом-спецификаторе-производном классе.

- Затем прямые базовые классы инициализируются в порядке объявления, как они появляются в списке-спецификаторе-базовом (независимо от порядка инициализаторов mem).

- Тогда, не статические данные инициализируются в порядке, они объявлены в определении класса (опять же, независимо от порядка MEM-инициализаторах).

- И наконец, составная инструкция корпуса конструктора выполнена.

[Примечание: Порядок декларации поручено обеспечить базовые и члены субобъекты разрушаются в обратном порядке инициализации. - конец примечание]

0

В сегменте кода:

UseResources() : Bonk(), Og() { 
     out << "UseResources()" << endl; 
    } 

На самом деле вы звоните UseResources конструктор перед созданием членов Бонк О.Г., но только outstreaming ваш журнал позже

1

Порядок конструктора звоните:

  1. Базовый класс.
  2. Члены, чтобы они отображались в заголовке
  3. Конструктор классов.

Класс UseResources «сконструирован» перед тем, как вызывается тело конструктора, имеющего размер, и переменные-члены, имеющие соответствующие адреса. Однако они еще не полностью построены.

Тело конструктора может предполагать, что все его элементы уже полностью построены (с их названными конструкторами), поэтому их нужно вызывать в этом порядке.

Таким образом, у Bonk и Og есть свои конструкторы, вызываемые в этом порядке перед UseResources.

Смежные вопросы