Link to home
Start Free TrialLog in
Avatar of muttley3141
muttley3141

asked on

Can I call member functions inside a constructor function ?

I often declare/define an Empty() member function for my classes, to make sure it's in a known
state with all held resources released.

I call this Empty() member in my constructors and destructors and throughout the program.

However, I've been recently experiencing weird GPFs, programs just exiting abruptly, and pointer-incrementing not working correctly (!). These faults were eventually traced to having the Empty() call in my constructors; removing the Empty() call (or making it an inline) made the program work correctly.

I'm aware that a general Empty() won't work inside a constructor because if you have something like:
if (ptr!=NULL) free(ptr) inside your Empty() and that ptr (member of MyClass) is set to a random value by the time the constructor is called, freeing it is a bit silly.

However, I am very careful to make sure that I initialise all such pointers that will be used by the Empty() as NULL in the constructor before the Empty() is called. nevertheless, I stil get weird happenings.

Is this an MFC-specific thing, or should I generally never use member functions inside constructors, on the basis that the object isn't fully constructed yet ?

If so, what's the best strategy for non-duplication of code between the "construct" and "empty" functions when you have a lot of member variables that need to be initialised ? Having to write out what amounts to the same code in the two cases is a bit excesive.


Richard [in SG1]
CMyClass
{
public:
  CMyClass();
  ~CMyClass();
  void Empty();
private:
  // arbitrary data members
};
 
CMyClass::CMyClass()
{
  // .. Set various resource holders to NULL.f
  Empty();
}
 
CMyClass::~CMyClass()
{
  Empty();
}
 
void CMyClass::Empty()
{
  // release resources.
}

Open in new window

SOLUTION
Avatar of jkr
jkr
Flag of Germany image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of muttley3141
muttley3141

ASKER

OK. I'll try and rebuild my code to demonstrate the problem. I'll do that tomorrow.
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
evilrix wrote this:

> With the exception of virtual functions it is perfectly safe .....

Ah. Maybe it was a virtual function where I was trying to call an Empty() from inside a constructor.

It'l take me some time to get sample code ready (my subversion server is down !). I didn't post it originally because I was expecting a plain "you can't do that" or "the VC++6.0 compiler is buggy in that respect".

I hadn't thought about the virtual-ness of the functions at the time.
Hi Muttley3141.

Did you get to the bottom of this in the end? Hopefully our answers helped, but I'd like to be sure we did solve your problem. Was you calling a virtual function? Was it caused by something else? I'm just curious as I hate not finding out the solution to a riddle :)

Cheers.

-Rx.
Well, no, I didn't really get to the bottom of things. I found out that it wasn't a virtual function in question, but a templated one. Templates confuse me and I had to re-do it for other reasons anyway.

Due to the size of the code, I can't really isolate the bit which is causing the problem, so I had to rewrite things.

The basic problem was that I had implemented a "list" class of my own but whenever I called a "Remove(i)" operation on it, the program GPFed. I found then that it worked perfectly if I put my Empty() function's contents, unrolled, inside the constructor, so that the Empty()er and the constructor were effectively running the same code. This is what made me think that putting calls to members inside a constructor was verboten.

I don't know much about templates and try to avoid them, but I do know that they are implemented in a manner similar to textual substitution and not in a manner similar to C++ polymorphism.

So, I still don't know what's going on here.



>> I don't know much about templates and try to avoid them
Templates are fantastic... I love them :) You can do so many cool things with templates, seriously try and embrace them, they can make writing c++ code so much simpler once you get the hang of them

The following is a good link about template basics
http://www.cplusplus.com/doc/tutorial/templates.html

>> but I do know that they are implemented in a manner similar to textual substitution
Not really. The difference between templates and #define's (which really are text substitution) is that templates are instantiated (that's what we call it when the compiler injects the templates code) by the compiler, and they are first class C++ constructs and fully obey all the rules of C++.

I suspect the problem isn't so much because the code is templated but; rather, the compiler is generating code that you didn't expect.

>> and not in a manner similar to C++ polymorphism.
Templates are, in fact, a form of polymorphism. The difference is the polymorphism you refer to is runtime polymorphism provided by the late-binding mechanism, which we call dynamic polymorphism. Templates (and function overloading) and a form of static polymorphism, which is resolved by the compiler and compile time. See example, below.

If you' like to get to the bottom of this (and it is usually a good idea to try and understand a problem because otherwise you can't be sure you've actually fixed it... maybe you've just hidden it and at some point it'll come back and bite you) I'd be more than happy to look at a sample of the original code to see if I can spot where it's going wrong.


#include <iostream>
 
enum OUTPUT_TYPE
{
	OUTPUT_FOO,
	OUTPUT_BAR
};
 
template <OUTPUT_TYPE>
class outputterT;
 
template <>
class outputterT<OUTPUT_FOO>
{
public:
	void operator()() const
	{
		std::cout << "foo" << std::endl;
	}
};
 
template <>
class outputterT<OUTPUT_BAR>
{
public:
	void operator()() const
	{
		std::cout << "bar" << std::endl;
	}
};
 
typedef outputterT<OUTPUT_FOO> outputterFoo;
typedef outputterT<OUTPUT_BAR> outputterBar;
 
template <typename OUTPUT_TYPE OT>
void Output(outputterT<OT> const & outputterConcept)
{
	outputterConcept();
}
 
int main(int argc, char* argv[])
{
	outputterFoo foo; // Output concept for foo
	outputterBar bar; // Output concept for bar
 
	// Static polymorphism in action
	Output(foo);
	Output(bar);
}

Open in new window