Я уже некоторое время работаю в C++, но раньше я никогда не сталкивался с этой ошибкой. У меня есть структура (с именем skew_value), которая имеет метод инициализации, так что все может иметь правильные значения по умолчанию (если у него больше конструктора и деструктора, я делаю его классом вместо структуры). Я проверил, что конструктор действительно называется (точки останова). И переменные правильно установлены. Но как только конструктор закончен, все неинициализировано.
Код выглядит следующим образом:
#ifndef _LBMOON_GRAPHICSYSTEM_SKEW_VALUE_H
#define _LBMOON_GRAPHICSYSTEM_SKEW_VALUE_H
struct skew_value
{
skew_value(float tlX=1, float tlY=0, float trX=0, float trY=0, float blX=0, float blY=0, float brX=0, float brY=0)
{
skew_value(Vector2f(tlX,tlY), Vector2f(trX,trY), Vector2f(blX,blY), Vector2f(brX,brY));
}
skew_value(Vector2f topLeft, Vector2f topRight, Vector2f bottomLeft, Vector2f bottomRight)
{
TLSkew = topLeft;
TRSkew = topRight;
BLSkew = bottomLeft;
BRSkew = bottomRight;
xScale = 1;
yScale = 1;
}
float xScale;
float yScale;
Vector2f TLSkew;
Vector2f TRSkew;
Vector2f BLSkew;
Vector2f BRSkew;
Vector2f TLOrigin;
Vector2f TROrigin;
Vector2f BLOrigin;
Vector2f BROrigin;
unsigned int TLIndex;
unsigned int TRIndex;
unsigned int BLIndex;
unsigned int BRIndex;
};
#endif
Vector2f - это класс, содержащий две поплавковые переменные. Масштабирование обычно является одним из них, но я переключил его на две переменные с плавающей точкой, чтобы проверить, что проблема не лежит в классе Vector2f.
Любое объяснение, которое вы можете указать, почему вызывает конструктор, но тогда все переменные, которые были деинициализированы, были бы большими. Это происходит, если я сделаю класс указателем или нет. Также не имеет значения, какой конструктор я вызываю, или если я предоставляю аргументы. Он просто отказывается отслеживать данные после вызова конструктора.
Проблема в том, что вы не возвращаете объект, который вы инициализируете, с этими значениями. Ваш вызов конструктора skew_value
с использованием аргументов float аргументирует и инициализирует временный анонимный автоматический объект skew_value
но не копирует его в объект, который вы планируете создавать, и не модифицирует его. Таким образом, изменения не отражаются в конечном итоге.
C++ не является Java или С#, где вы можете вызвать вложенные конструкторы изначально таким образом (из тела функции).
Однако...
C++ 11 представила эту способность; вы просто не используете для этого правильный синтаксис. Он должен называться как аргумент списка инициализатора.
Вместо этого вы должны сказать:
struct skew_value
{
skew_value( float tlX=1, float tlY=0, float trX=0,
float trY=0, float blX=0, float blY=0,
float brX=0, float brY=0)
: skew_value( Vector2f( tlX, tlY ),
Vector2f( trX, trY ),
Vector2f( blX, blY ),
Vector2f( brX, brY ) )
{
}
skew_value(Vector2f topLeft, Vector2f topRight,
Vector2f bottomLeft, Vector2f bottomRight)
{
TLSkew = topLeft;
TRSkew = topRight;
BLSkew = bottomLeft;
BRSkew = bottomRight;
xScale = 1;
yScale = 1;
}
....
}
Если функции C++ 11 не могут использоваться
Тогда вам придется сделать это долгий путь, и снова он предложил использовать список инициализаторов для инициализации всех ваших значений.
Дополнительная ссылка
Найдите больше в этом связанном вопросе, который может быть дубликат: Можно ли вызвать конструктор из другого конструктора (сделать цепочку конструктора) в C++?
В этом коде,
skew_value(float tlX=1, float tlY=0, float trX=0, float trY=0, float blX=0, float blY=0, float brX=0, float brY=0)
{
skew_value(Vector2f(tlX,tlY), Vector2f(trX,trY), Vector2f(blX,blY), Vector2f(brX,brY));
}
вызов конструктора посередине создает временную инициализацию.
C++ 11 поддерживает переадресацию конструктора, но имеет другой синтаксис, я никогда не использовал его, и ваш компилятор может не обязательно поддерживать его.
Вместо этого я предлагаю использовать либо конструктор базового класса, либо функцию фабрики объектов. Я бы не использовал метод init
, потому что есть серьезные причины (некоторые из них обсуждались Бьярне в его приложении по безопасности при исключении к третьему изданию "Язык программирования C++"). Но в конце концов это может быть то, что вы закончите, и это не так опасно, пока вы не начнете требовать, чтобы клиентский код вызывал его.
Обратите внимание, что вы оставляете переменные-члены TLIndex
, TRIndex
, BLIndex
и BRIndex
неинициализированными. Это означает, что они будут иметь неопределенные значения. С некоторыми компиляторами и параметрами эти значения будут равны 0, но с другими они будут более явно произвольными, и это может быть легко источником ошибок.
Также обратите внимание, что символ препроцессора
_LBMOON_GRAPHICSYSTEM_SKEW_VALUE_H
является недействительным. Все имена, смотрящие с подчеркиванием, за которым следует буква верхнего регистра, зарезервированы для реализации. И имена, содержащие два последующих символа подчеркивания.
В этом случае я сомневаюсь, что вы получите какой-либо непреднамеренный эффект замены текста или переопределения, но действительно извращенный компилятор может рассматривать это как ошибку, и в любом случае это плохая привычка, которую лучше всего исправлять. ;-)
this
в этом утверждении :-) конечно, хороший намек