Re: [RESOLVED] Can you call a constructor twice
Quote:
Originally Posted by ovidiucucu
[ Redirected thread ]
Q: Can I call a constructor twice?
A: Yes, you can (although you may not).
Try this little program
Code:
#include <iostream>
using namespace std;
class CFoo
{
public:
CFoo() {cout << "CFoo::CFoo - this is: " << this << endl;}
void* operator new(size_t, void* p) {return p;}
};
int main()
{
CFoo foo;
new(&foo)CFoo; // constructor called twice
return 0;
}
Of course, the previous answers are good. I have posted that just as an aside "curiosity"... ;)
Lol I don't know alot of that syntax but if you say that you can call a constructor twice, and other people say you can't, then who do I listen to? Haha.
Quote:
Code:
Completely identical - NO.
MYObject::MyObject()
{
Initialize();
}
MyOBject::Initialize()
{
//Variable assignments here
}
Let me see if I've got this right... the order of execution will be:
constructor (doesn't initiliase) > intiliase() > initiliases variables > leaves initiliase() > leaves constructor
I can't see for the life of me see the purpose of that! All it's doing is making another function do what the constructor does... and once! What I asked was if you can call a constructor twice.
So: constructor initialises variables > in a member function the variables get messed around with > constructor gets called again to initialise variables back to their default
Two people posted the same code but all it does is chuck a function into a constructor that does the constructor's job... I just don't see the point in it.
It's not that important that I find out the answer to this question, but I was just curious because it is easier than creating another function to initiliase a class's variables a second time.
Edit: Why is this in Non-Visual C++? I'm using VS.
Re: [RESOLVED] Can you call a constructor twice
That code posted by Ovidiu uses the placement new operator. But that can be disastrous and it is probably undefined behaviour by the standards. You should not be doing that and that is what Ovidiu tells when he say "(although you may not)."
Hobson's post illustrates how you would do it.. but you may want to change the init call from the constructor to actual initialization in the initializer list. It would suffer from a problem though, every time a new data member is added to the class - you would need to make changes at atleast 2 places - the constructor and the init() function while with Hobson's way you would need to do it at one place only.
init() can be overloaded as well to have different set of assignments. Also, it would be better to call this function reset() (more meaningful to me) but it really is your choice.
Re: [RESOLVED] Can you call a constructor twice
In fact forget about calling twice, you cannot call the constructor explicitly even once (except for using the placement new syntax but that is not what you are doing).
Do you anywhere see that you are even calling the constructor once? Let me know where... It is being called automatically upon creation of the object. So, what is being told to you is that the constructor gets called only when the object is being constructed. Never again. With the member function init() what you are doing is delegating the initialization to the init function. The members of the class that Hobson has used are POD types and hence their initialization doesn't happen by default in the constructor - they remain uninitialized. The init function does that. init() is just another member function. You can call it from anywhere - the constructor, destructor, any other member function of the class or from user code using the object of that class. So, what is being done the second time is just that the member variables are being set to the mentioned values. The constructor is not being called.
If it helps you can imagine the second call to init() as being 2 setter functions that are being called to set each of the two member variables.
How that looks like a constructor call to you is unimaginable by me! Again, as I said earlier, forget about calling the constructor twice, you don't even call it once yourself!
Re: [RESOLVED] Can you call a constructor twice
So you can't call a constructor full stop? Thanks. And if I wanted to intialise variables I'd have to create a separate function? That's all I wanted to know.
Edit: The thing that I still don't understand though, is why 2 people would suggest to call a intialise function from within a constructor...
Re: [RESOLVED] Can you call a constructor twice
Quote:
Originally Posted by Mybowlcut
Edit: The thing that I still don't understand though, is why 2 people would suggest to call a intialise function from within a constructor...
That is because you wanted to be able to "reset" the object to the state it had when you constructed it. Easiest way to do this is like Hobson showed you!
Regards,
Laitinen
Re: [RESOLVED] Can you call a constructor twice
There is a rule which says something like: Each logical task shoud be performed in dedicated function. And each function should perform only one logical task. In your case, this logical task is to set members to theirs initial state. This task is to be performed more than once, not only at the beginning of the object lifetime. So just create ONE function (called reset or init or whatever) and call it when appropriate. You do not have to call this function inside of constructor, if you really do not want to. You may call it later, when object is already constructed:
Code:
CFoo foo;
.... some code, and later
foo.init();
But in such a case you might to forget (or miss from any else reason) to call initializer. If initialization would be performed only once, you'd be able to set values to members in constructor initialization list (again, not in constructor itself!).
I think that you just misunderstood the meaning of constructor. Constructor is NOT an initializer. It may be, but it does not have to. Sometimes it is even impossible to initialize an object inside of constructor, thats how all MFC works: you always have to call CWnd::Create after creating CWnd object.
The reason why I did not use initializer list in my example is that because I think it would be pretty useless to create two different snippets of code with the same functionality. At least in this case.
You also could to completely recreate your object, but that not always would be good:
Code:
CFoo foo; //call constructor for the first time ;)
MessWithMyFoo(foo);
foo = CFoo(); //init foo with brand new CFoo, almost by calling ctor second time (pun indented)
Above has a drawback that it creates completely new CFoo object and there is no way to reinitialize only some members, and keep some others unchanged.
I am sorry, but I do not know how to say it more clearly.
Cheers,
Hob
Re: [RESOLVED] Can you call a constructor twice
Quote:
Originally Posted by Mybowlcut
... The thing that I still don't understand though, is why 2 people would suggest to call a intialise function from within a constructor...
I also cannon understand why only 2...? :confused:
Or you cannot count?! :wave: :rolleyes:
All people in this thread (except you) suggested the same - implement the additional method called initialize or init or reset or whatsever ... serving for your purpose - set the default valuesf or the class object!
Re: [RESOLVED] Can you call a constructor twice
There is no full stop. You did not understand. Probably you need to read up on constructors a little bit and my posts again.
Initialization happens in constructors but you do not call the constructors. When you declare an object it is called automatically and not explicitly by you. Now, constructors are the place where initialization happens - you can leave the initialization empty - in which POD are uninitialized and non-POD are default initialized. You can write initialization code in the initializer list. You can write code in constructor body (but that is not initialization, that is assignment) and you can take that all code in another function and call that function from the constructor.
I don't understand what you are not understanding, or where you are confusing. Can you post some code upon your understanding or misunderstanding that we can say is right or wrong and then may be you can conclude?
Re: [RESOLVED] Can you call a constructor twice
Ovidiu's "curiosity" just made my teeh grind... :D "Curiosities" like this one are nasty thing, harmless for poster, and make their readers fat :no-no-handshoe:
Re: [RESOLVED] Can you call a constructor twice
Hobson you said it very clearly. Everyone has been very patient but exterminator has given me an idea, so:
Code:
class Test
{
public:
Test(); //constructor
void mess();
private:
int a;
int b;
}
Test::Test(): a(0), b(0) {} //initialise private data members a and b to 0
void Test::mess()
{
a = 1; // mess around with data members
b = 1;
}
int main()
{
Test myTest; //constructor is called
myTest.mess(); //change variables
myTest.Test(); //constructor called again to intialise values back to original
return 0;
}
Ok. I was just interested to know if this would ever work and if it does, if it's bad programming practice.
Re: [RESOLVED] Can you call a constructor twice
No, it is not possible.
Things which are possible to say:
- "Look, this line creates new local object, and this causes constructor to be executed!"
- "Look, I created object with operator new, and constructor was executed!"
- "Yay, when I am creating a temporary object, ctor runs!"
You know that someone is a nasty liar, when he says:
- "I just called a constructor [explicitly] for this object!"
Like exterminator said, there is no way to call ctor explicitly. By 'no' I mean very no. Ctor is called implicitly when new objct is created, in any manner: local, globa, static, temporary, new, placement new. But no creation - no ctor call.
Cheers
Re: [RESOLVED] Can you call a constructor twice
Quote:
Originally Posted by Mybowlcut
Code:
class Test
{
public:
Test(); //constructor
void mess();
private:
int a;
int b;
}
...
int main()
{
Test myTest; //constructor is called
myTest.Test(); //constructor called again to intialise values back to original
return 0;
}
Ok. I was just interested to know if this would ever work and if it does, if it's bad programming practice.
It just won't (at least, it should NOT) be compiled!
My VC++ 6 compiler displays:
Quote:
error C2274: 'function-style cast' : illegal as right side of '.' operator
Re: [RESOLVED] Can you call a constructor twice
To summarize:
1) the constructor can not "be called" twice (technically
not even once). (Constructors do not have names and you
can not take the address of the constructor).
2) What Ovidiu did was create a SECOND object (but at the
same location as the first). So TWO objects are created,
but only ONE destructor will be called. Run the following
code and watch the memory (using task manager/top).
Code:
#include <string>
class CFoo
{
public:
CFoo() : s("Hello World") {}
void* operator new(size_t, void* p) {return p;}
std::string s;
};
int main()
{
CFoo foo;
// when you want to "reinitialize"
while (true)
{
new (&foo) CFoo;
}
return 0;
}
3) You can use the following to create a new object on top of
the old one, without the memory leak (assuming the alignment
of the char array is compatible with the alignment for a CFoo
object).
Code:
#include <string>
class CFoo
{
public:
CFoo() : s("Hello World") {}
void* operator new(size_t, void* p) {return p;}
std::string s;
};
int main()
{
char memory_pool[ sizeof(CFoo) ];
CFoo * pFoo = new (memory_pool) CFoo;
// use pFoo ...
// when you want to "reinitialize"
while (true)
{
pFoo->CFoo::~CFoo(); // destroy old object
pFoo = new (memory_pool) CFoo; // create a new object
}
// if the loop was such that you could exit from it, you
// would need to call the destructor if not already done.
return 0;
}
Re: [RESOLVED] Can you call a constructor twice
One or two more posts about placement new and I bet that very soon we will read about some production code nonsensically using it at www.TheDailyWTF.com :D
Re: [RESOLVED] Can you call a constructor twice
Case closed! My question has been answered! Thanks guys. :)
BTW anything involving new I don't understand sorry to say.