воскресенье, 20 февраля 2011 г.

44. В каком порядке инициализируются поля в классе? Совпадает ли этот порядок с порядком перечисления инициализаторов в списке инициализации конструктора?

struct A1{
  A1(){cout<<1;}
};

struct A2{
  A2(){cout<<2;}
};

class B{
  A1 x;
  A2 y;
public:
  B():y(),x(){}
};

int main() {
  B b;
}

Сначала объявлен член x, затем y. А в списке инициализации обратный порядок. Посмотрим что важнее. Запускаем. Получим "12". Все верно, ведь инициализация происходит в порядке объявления их в классе, а не в списке инициализации (так написано в спецификации).

А еще MinGW предупреждает:
In constructor 'B::B()':
|18|warning: 'B::y' will be initialized after
|17|warning: 'A1 B::x'
|20|warning: when initialized here


y будет проинициализирован позже, чем x, несмотря на порядок в списке инициализации.

пятница, 18 февраля 2011 г.

43. Каким образом разрешается инициализировать константные поля в классе?

Я уже насписал в ответе на "42. Как объявить константу в классе? Можно ли объявить дробную константу?". Вкратце:
class A{
  const T i;
  static const T i1 = 1; /* Если T - неинтегральный тип, может не сработать */ 
  static const T i2;  /* Для неинтегральных типов здесь только объявить, а проинициализировать позже */
  A():i(const_value){}
};

const T A::i2 = const_value;

К интегральным типам относятся char, short, int и long.

Есть еще один способ создания констант в классе, это enum hack. Изменим пример из ответа на 42-й вопрос.
class Year {
  /*...*/
  enum {MIN_YEAR = 1900, MAX_YEAR = 2100};
  /*...*/
}

четверг, 17 февраля 2011 г.

42. Как объявить константу в классе? Можно ли объявить дробную константу?

Сначала нужно подумать, что может означать "константа в классе". Попробую использовать относительно реальные примеры, а не мой любимый "class A" :)

Первый случай

Допустим, мы пишем класс Polygon (многоугольник). Мы хотим, чтобы количество вершин задавалось при создании объекта.
class Polygon{
  int vertexes;
public:
  Polygon(int v):vertexes(v){}
}
Таким образом, при создании экземпляра будет необходимо задать количество вершин, так как конструктора по умолчанию уже нет. Все хорошо, но в какой-нибудь функции-члене можно ненароком изменить vertexes, а мы этого не хотим. Тогда и добавляем модификатор const.
const int vertexes;
Значение такой переменной можно задать только в списке инициализации конструктора, как и сделано в примере. А вот так даже и не пытайтесь:
Polygon(int v){vertexes = v;} /*ошибка*/
см. также Страуструп 10.4.6.1. "Необходимая инициализация членов"

Второй случай

У нас есть класс Year, и мы хотим, чтобы задаваемый год не выходил за границы диапазона
const int MIN_YEAR = 1900;
const int MAX_YEAR = 2100;
const int DEFAULT_YEAR = 2011;

class Year{
  int year;
public:
  Year(int y);
};

Year::Year(int y){
  if(y < MIN_YEAR || y > MAX_YEAR){
    y = DEFAULT_YEAR;
  }else{
    year = y;
  }
}
Хорошо было бы, если класс не молчал, а как-то предупреждал о выходе за пределы, например генерировал исключение, но это пока не важно. Я хочу поместить эти константы в класс. Способ из предыдущего примера явно не подходит. Тут явно напрашивается связь со статическими членами. Так и есть, можно использовать статические константные члены.
class Year{
  int year;
  static const int MIN_YEAR = 1900;
  static const int MAX_YEAR = 2100;
  static const int DEFAULT_YEAR;
public:
  Year(int y);
};

const int Year::DEFAULT_YEAR = 2011;

Year::Year(int y){
  if(y < MIN_YEAR || y > MAX_YEAR){
    year = DEFAULT_YEAR;
  }else{
    year = y;
  }
}
Обратили внимание, что DEFAULT_YEAR проинициализирован за пределами класса? Да, можно и так. А с дробными, согласно спецификации, только так.

Можно ли объявить дробную константу?

Вопрос относится ко второму случаю, с первым (класс Polygon) все нормально.
Дробную объявить можно, но проинициализировать только аналогично способу инициализации DEFAULT_YEAR. Однако в спецификации нет явного запрета на:
class A{
  static const double PI  = 3.1415;
}
MinGW на это не ругается, VS не знаю. Почему так сложно с дробными? Я и сам не понял, можно почитать ветку форума, там вроде все выяснили.

вторник, 15 февраля 2011 г.

Сервис Connecting Bloggers

Мы решили сделать сервис, которые делает тоже самое, автоматически, на основе информации из ваших блогов — мы берем ваши посты, выбираем картинки к ним (если картинки нет, то пытаемся найти в интернете подходящую) и генерируем информер, который вставляется в блог.
http://habrahabr.ru/blogs/blogosphere/113613/
Ради любопытства прикрутил виджет, его можно видеть справа. Автоматически подбирающиеся картинки, конечно не в тему, но иногда бывают забавными, пусть пока побудут.

понедельник, 14 февраля 2011 г.

Страуструп "Язык программирования C++". Специальное издание 2011.

Забывал написать. Наконец-то переиздали. Заказал в декабре, получил 31-го, прямо под новый год.
На Озоне аж 924 рубля.
На books.ru - 622.
А я брал здесь за 684. Удобно, что посылку можно забрать в пункте выдачи заказов и там же оплатить по ее прибытии.