C ++ инициализация членов класса вложенными конструкторами - PullRequest
3 голосов
/ 06 января 2012

Можно ли инициализировать такой класс?

Quaternion::Quaternion(){ //default without arguments
    Quaternion(0.,V3(0.,0.,0.));
}


Quaternion::Quaternion(double s, V3 v){ //with scalar and vector as a argument
    coords[0] = s;
    coords[1] = v[0];
    coords[2] = v[1];
    coords[3] = v[2];
}

потому что это вывод:

QUATERNION TEST
(2.122e-313:-3.22469e-232:2.122e-313:-1.998) //instanciated with Quaternion q;
(4:1:2:3) // instanciated with the Quaternion q(4,1,2,3);
(4:-1:-2:-3) // conjugated of the one above

и первый не инициализируется как 0. как и должно быть ... почему?

Ответы [ 5 ]

13 голосов
/ 06 января 2012

Не в C ++ 03, но последняя версия C ++ позволяет делегировать конструкторам:

Quaternion() : Quaternion(0.0, V3(0.0,0.0,0.0)) { }

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

До C ++ 11 вы действительно не можете обойтись без копирования / вставки, если вы действительно хотите инициализировать ваши ученики прямо в конструкторе.Может быть, вы хотели бы использовать аргументы по умолчанию, хотя?Некоторые люди возражают против этих ....

explicit Quaternion(double s = 0.0, V3 v = V3(0.0,0.0,0.0)) { /* ... */ }
4 голосов
/ 06 января 2012
Quaternion(0.,V3(0.,0.,0.));

Это не вызывает другого конструктора; вместо этого он создает локальный временный объект, который сбрасывается при возврате конструктора.

В C ++ 03 ваши единственные возможности - инициализировать все члены в обоих конструкторах или переместить инициализацию в отдельную функцию, которую вызывают оба конструктора.

В C ++ 11 вы можете делегировать другому конструктору, используя немного другой синтаксис:

Quaternion::Quaternion() :
    Quaternion(0.,V3(0.,0.,0.))
{}
2 голосов
/ 06 января 2012

Эта функция называется делегированием конструкторов и фактически была представлена ​​в C ++ 11, ранее она была недоступна. Обратите внимание, что фактический синтаксис выглядит иначе:

Quaternion::Quaternion() //default without arguments
  : Quaternion(0.,V3(0.,0.,0.)) // delegating constructor
{
}


Quaternion::Quaternion(double s, V3 v) //with scalar and vector as a argument
  : coords{ s, v[0], v[1], v[2] } // better version if you're using C++11 anyways
{
}

Ваш код сделал то, что он создал временный Quaternion объект, который был немедленно уничтожен.

1 голос
/ 06 января 2012

Конструктор по умолчанию просто вызывает конструктор с двумя аргументами. Затем помещает полученный объект в стек и деконструирует его, когда он покидает конструктор.

Таким образом, кватернион с 0 инициализацией действует только во время построения кватерниона без аргументов, но это не кватернион, который создается конструктором по умолчанию.

Что вы можете сделать, это назначить стандартные значения для параметров:

#include <cstdio>

class TestCl {
public:
  TestCl(int i = 0) {
    printf("%d\n", i); 
  };
};

int main(int argc, char** argv) {
  TestCl f(1);
  TestCl s;
  return 0;
}
1 голос
/ 06 января 2012

Вы создаете временный экземпляр в Quaternion::Quaternion(). Если вы не хотите создавать каждый конструктор, определите функцию-член инициализации, такую ​​как init(), или подождите, пока в вашем компиляторе не будет реализован делегирующий конструктор в C ++ 11.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...