Переменные, инициализированные в конструкторе, не остаются инициализированными (c ++)

0

Я уже некоторое время работаю в 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.

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

  • 1
    При использовании вашего отладчика ищите значение этого в различных вызовах конструктора. ;-) ideone.com/tNMi37
  • 0
    Вы должны добавить акцент на слово this в этом утверждении :-) конечно, хороший намек
Теги:
c++11
visual-c++
variables
constructor

2 ответа

7
Лучший ответ

Проблема в том, что вы не возвращаете объект, который вы инициализируете, с этими значениями. Ваш вызов конструктора 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++?

  • 0
    Большое вам спасибо ^. ^ Теперь я точно понимаю, как это все работает. Теперь мне нужно исправить некоторые другие мои структуры, которые я не удосужился проверить, в которых я совершил ту же ошибку, смеется. Я очень ценю вашу помощь!
0

В этом коде,

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

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

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


Ещё вопросы

Сообщество Overcoder
Наверх
Меню