2015-01-07 4 views
0

Я следующее определение класса в C++:Вызов конструктора для инициализации переменных

class foo { 
private: 
    int  a,b,c; 

    foo();  // constructor 
    void  setup(int x, int y); 
    void  some_function_that_changes_a_b_c(); 
} 


foo::foo() { 
    a = b = c = 0; 
} 

void foo::setup(int x, int y) { 
    foo(); // <-- I use this to make sure a,b,c are initialized 
    a = x; 
    b = y; // <-- c is left unchanged! 
} 

void foo::some_function_that_changes_a_b_c() { 
    // here's some code that changes variables a,b,c 
} 

А то у меня есть код, который использует этот класс:

foo *a = new foo; 
a->setup(1,2); 
a->some_function_that_changes_a_b_c(); 
a->setup(5,7); // <-- HERE IS THE PROBLEM 

Проблема заключается в том, что на второй вызов to setup(), он не запускает конструктор foo() для сброса моих значений или a, b, c, поэтому переменная c остается со старым значением, которое было при вызове some_function_that_changes_a_b_c(), я проверил это с помощью отладчика и похоже, что во втором вызове foo() обращается к другому пространству памяти для переменных.

Есть ли способ исправить это?

+0

** Книга: ** https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list – Galik

+0

вы должны использовать функцию для инициализации свойств, а не непосредственно делать это в конструкторе – Hacketo

+0

Это уже было рассмотрено здесь - http://stackoverflow.com/questions/14402097/calling-class-constructor-in-member-function-c-solved – raveesh

ответ

4

В C++ конструктор вызывается только один раз, когда объект сконструирован, а не больше в вашем методе класса. В коде

void foo::setup(int x, int y) { 
    foo(); // ==> this line 
} 

временный объект Foo будет создан, который не зависит от текущего this объекта, и поэтому a, b и c поле this объекта будет неизменным.

Для того, чтобы сделать то, что вы имеете в виду, создать метод класса, скажем foo::reset(), и называют его изнутри foo::setup().

1

Вы не должны вызывать свой конструктор после того, как объект был создан. Поместите функциональность в защищенную функцию reset(), которая вызывается как из вашего конструктора, так и из функции setup.

фона: Ваш призыв к foo() в setup не переинициализировать объект, но создать второй локальный объект, который никогда не используется. В общем, вы должны воздерживаться от явного вызова конструкторов, если вы не знаете, что делаете.

1
foo(); // <-- I use this to make sure a,b,c are initialized 

К сожалению, это не так. Он создает и уничтожает временный объект. Вы не можете вызвать конструктор напрямую; они используются только для инициализации объектов в начале их жизни.

Вы можете переназначить ваш объект с свеже инициализируется один:

*this = foo(); 

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

Мой предпочтительный вариант будет использовать отдельные объекты, а не пытаться повторно использовать модифицированную один, и выполнить все «настройки» при инициализации каждого объекта:

foo a(1,2); 
a.some_function_that_changes_a_b_c(); 
foo b(5,7); // known to be in a freshly initialised state 
0

То, что вы пытаетесь сделать, это двух- этап инициализации. Это не нужно и неуклюже в C++.Вы должны понимать две вещи

  1. Конструктор вызывается в момент создания объекта

  2. Если у вас есть объект, чтобы сказать f.setup(1, 2, 3); на, это означает, что конструктор должен быть работать уже.

Сейчас:

foo f; // calls foo() with f 
f.setup(1, 2, 3); // foo() has arleady been called 

в Ин Сюн указал, то foo() линия создает временный объект, не имеющие отношения к this вы работаете.

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

class foo { 
    private: 
    int  a,b,c; 
    public: 
    foo(int x, int y, int z);  // constructor 
}; 

foo::foo(int x, int y, int z) 
    : a(x), 
    b(y), 
    c(z) 
{ } 

, а затем вместо того, чтобы строить со значениями вы хотите

foo f(1, 2, 3); 

если вам нужно «перезагрузить» значения каждый раз, когда вызывается setup, тогда вы лучше всего используете функцию reset или аналогичную. Попытка вызвать конструктор на себя возможна, но не очень здоровая.

void foo::reset() { 
    a = b = c = 0; 
} 
Смежные вопросы