Интернет, компьютеры, софт и прочий Hi-Tech

Подписаться через RSS2Email.ru

Страница 6 из 10 - Предыдущая - Следующая
Все страницы - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10

Краткий FAQ по C++

[10.7] Можно ли пользоваться указателем this в конструкторе?

Некоторые люди не рекомендуют использовать указатель this в конструкторе, потому что объект, на который указывает this еще не полностью создан. Тем не менее, при известной осторожности, вы можете использовать this в конструкторе (в {теле} и даже в списке инициализации [10.6]).

Как только вы попали в {тело} конструктора, легко себе вообразить, что можно использовать указатель this, поскольку все базовые классы и все члены уже полностью созданы. Однако даже здесь нужно быть осторожным. Например, если вы вызываете виртуальную функцию (или какую-нибудь функцию, которая в свою очередь вызывает виртуальную функцию) для этого объекта, вы можете получить не совсем то, что хотели [23.1].

На самом деле вы можете пользоваться указателем this даже в списке инициализации конструктора [10.6], при условии что вы достаточно осторожны, чтобы по ошибке не затронуть каких-либо объектов-членов или базовых классов, которые еще не были созданы. Это требует хорошего знания деталей порядка инициализации в конструкторе, так что не говорите, что вас не предупреждали. Самое безопасное - сохранить где-нибудь значение указателя this и воспользоваться им потом. [Не понял, что они имеют в виду. - YM]

[10.8] Что такое "именованный конструктор" ("Named Constructor Idiom")?

Эта техника обеспечивает более безопасный и интуитивно понятный для пользователей процесс создания для вашего класса.

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

Для использования именованных конструкторов вы объявляете все конструкторы класса в закрытом (private:) или защищенном (protected:) разделе, и пишете несколько открытых (public:) статических методов, которые возвращают объект. Эти статические методы и называются "именованными конструкторами". В общем случае существует по одному такому конструктору на каждый из различных способов создания класса.

Например, допустим, у нас есть класс Point, который представляет точку на плоскости X - Y. Существуют два распространенных способа задания двумерных координат: прямоугольные координаты (X + Y) и полярные координаты (радиус и угол). (Не беспокойтесь, если вы не разбираетесь в таких вещах, суть примера не в этом. Суть в том, что существует несколько способов создания объекта типа Point.) К сожалению, типы параметров для этих двух координатных систем одни и те же: два числа с плавающей точкой. Это привело бы к неоднозначности, если бы мы сделали перегруженные конструкторы:

    class Point {
    public:
      Point(float x, float y);   // Прямоугольные координаты
      Point(float r, float a);   // Полярные координаты (радиус и угол)
    // ОШИБКА: Неоднозначная перегруженная функция: Point::Point(float,float)
    };

    int main()
    {
      Point p = Point(5.7, 1.2); // Неоднозначность: Какая координатная система?
    }

Одним из путей решения этой проблемы и являются именованные конструкторы:

    #include <math.h>              // Для sin() и cos()

    class Point {
    public:
      static Point rectangular(float x, float y);    // Прямоугольные координаты
      static Point polar(float radius, float angle); // Полярные координаты
      // Эти статические члены называются "именованными конструкторами"
      // ...
    private:
      Point(float x, float y);     // Прямоугольные координаты
      float x_, y_;
    };

    inline Point::Point(float x, float y)
    : x_(x), y_(y) { }

    inline Point Point::rectangular(float x, float y)
    { return Point(x, y); }

    inline Point Point::polar(float radius, float angle)
    { return Point(radius*cos(angle), radius*sin(angle)); }

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

 int main()
 {
   Point p1 = Point::rectangular(5.7, 1.2);// Ясно, что прямоугольные координаты
   Point p2 = Point::polar(5.7, 1.2);      // Ясно, что полярные координаты
 }

Обязательно помещайте ваши конструкторы в защищенный (protected:) раздел, если вы планируете создавать производные классы от Fred. [Видимо, ошибка. Хотели сказать - Point. - YM]

Именованные конструкторы также можно использовать в том случае, если вы хотите, чтобы ваши объекты всегда создавались динамически (посредством new [16.19]).

Страница 6 из 10 - Предыдущая - Следующая

Биржа долевых инвестиций SIMEX.

Последнее редактирование: 2009-10-02 16:27:41

Метки материала: C++, FAQ, программирование, конструкторы, this, именованный конструктор, Named Constructor Idiom, constructor, конструктор, виртуальная функция, базовые классы, инициализация, класс, статические методы, члены класса

Оставьте, пожалуйста, свой комментарий к публикации

Представиться как     Антибот:
   

Просьба не постить мусор. Если вы хотите потестить xBB, воспользуйтесь кнопкой предварительного просмотра на панели инструментов xBBEditor-а.


© 2007-2019, Дмитрий Скоробогатов.
Разрешается воспроизводить, распространять и/или изменять материалы сайта
в соответствии с условиями GNU Free Documentation License,
версии 1.2 или любой более поздней версии, опубликованной FSF,
если только иное не указано в самих материалах.