Jump to content
  • Advertisement
Sign in to follow this  
Clueless

About OOP and Constructors ...

This topic is 4879 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi again, everybody! A seemingly weird error made me realize that the constructors in C++ don't quite work like in Java. I tried to figure out how they work exactly by reading stuff I found ... but maybe I'm missing something. Is this correct: A derived class tries to call the constructor of the base class with its own parameters. So if I want to call the standard constructor without any parameters I have to call that one explicitly? For example:
     CLogfile::CLogfile( std::string filename )
     :   m_stream( filename.c_str() )
     {
         ddfileio::CResource::CResource();
(Java always tries to call a constructor without any parameters ...) Or is that the wrong conclusion? Anything else that I need to know about differences between Java and C++? Maybe there's a summary of differences between Java and C++ somewhere? Any why are the plus characters swallowed in Show Preview? ( isn't thaaat important, actually ;) )

Share this post


Link to post
Share on other sites
Advertisement
Quote:
Original post by Clueless
A derived class tries to call the constructor of the base class with its own parameters.


The base class is always constructed before a derived class, its either implicitly invoked or explicitly invoked by yourself in a constructor initializer list, if the base class does not have a default constructor you have to explicitly invoke it in all of the derived class constructors in there initializer list (except copy constructor which just implicitily or explicitly invokes the copy constructor of the base class).


Quote:
Original post by Clueless
So if I want to call the standard constructor without any parameters I have to call that one explicitly?

For example:
     CLogfile::CLogfile( std::string filename )
: m_stream( filename.c_str() )
{
ddfileio::CResource::CResource();
(Java always tries to call a constructor without any parameters ...)

Or is that the wrong conclusion?


if the base class has a default constructor and you don't invoke it in a constructor initializer list its implicitly invoked, if you want to explicitily invoke the default or another base constructor you do it in the initializer list:


derived::derived()
: base(...), foo(...), bar(...) {}


Quote:
Original post by Clueless
Anything else that I need to know about differences between Java and C++?
Maybe there's a summary of differences between Java and C++ somewhere?


That would take a entire book [wink]

Share this post


Link to post
Share on other sites
Thanks for your reply.
Not sure if I really understand that coreectly.
I thought copy constructor in the case of a Logfile would mean that another CLogfile pointer is passed as a parameter so that two similar instances exist?

That kinda wouldn't fit I guess.

Usually I don't pass any parameters ... then everything works fine.

In that one case I had to call the constructor without any parameters to add the logfile to the memory management part.

Is that what you call copy constructor? Constructors with the same parameter list?
Guess this sounds really ridiculous.

But from the explanation it still sounds either as if I shouldn't have to invoke:
ddfileio::CResource::CResource();

or as if I had to invoke almost all the constructors.

Btw ... if I put it in the initializer list it compiles but the constructor of the base class isn't actually called then.

Share this post


Link to post
Share on other sites
Quote:
Original post by Clueless
I thought copy constructor in the case of a Logfile would mean that another CLogfile pointer is passed as a parameter so that two similar instances exist?


a copy constructor is kinda special constructor which takes a constant reference to the same type in question i.e:


struct foo {

int j;

foo(int i = 0): j(i) {} // default constructor, becase it need no args

foo(const foo& f_ref): j(f_ref.j) {} // copy constructor

};
//....
int main() {

foo j = 40;
foo k = j; // uses copy constructor, makes k a copy of j
// k is independent of j and vice-versa
}


When you do not define a copy constructor and assignment operator one is implicitly defined by default (compiler generated) to do a member-wise (or bit-wise depending on context) copy/assign.

So generally you don't need to explicitly define them how-ever some times you do when the default is not appropriate for the context, for example if you had pointers to dynamically allocated memory and your destructor deletes it. The default behaviour would be a shallow copy and would invoke delete twice on the same area of memory!. So you would either disable copy/assignement by making them private or explicitly define them to do a proper deep copy or some other appropriate behaviour.

Quote:
Original post by Clueless
Usually I don't pass any parameters ... then everything works fine.


Yes if the base class has default constructor (which is typical) its implicity invoked weather you like it or not.

Quote:
Original post by Clueless
In that one case I had to call the constructor without any parameters to add the logfile to the memory management part.


Okay i'm not sure what your talking about here, code example of what you mean maybe?

Quote:
Original post by Clueless
Is that what you call copy constructor? Constructors with the same parameter list?
Guess this sounds really ridiculous.


I think i've explained above.


Quote:
Original post by Clueless
But from the explanation it still sounds either as if I shouldn't have to invoke:
ddfileio::CResource::CResource();

or as if I had to invoke almost all the constructors.


Yes if the base class has a default constructor then you don't need to explicitly invoke it its implicitly invoked for you.

Share this post


Link to post
Share on other sites
Ok ... pretty much what I thought.

The base classes all have standard constructors. I too thought they should be called automatically.

     class CResource: public ddmemory::CMemobject
{

public:// PUBLIC

//! Constructor: CResource()
CResource();

     class CMemobject: public CObject
{

public:// PUBLIC

//! Constructor: CMemobject()
CMemobject();


The derived class doesn't have a standard constructor without any parameters:
     class CLogfile: public ddfileio::CResource
{

public:// PUBLIC

//! Constructor: CLogfile( std::string filename )
CLogfile( std::string filename );


The impression I got is that in that case a constructor CResource( std::string filename ); would be called ... but CResource() isn't.

Is CResource( std::string filename ); the standard constructor in that case?
That was what I was trying to talk about ;)

Share this post


Link to post
Share on other sites
Quote:
Original post by Clueless
The impression I got is that in that case a constructor CResource( std::string filename ); would be called ... but CResource() isn't.

Is CResource( std::string filename ); the standard constructor in that case?
That was what I was trying to talk about ;)

If you don't call the baseclass constructor explicitly the constructor without any parameters will be called, regardless of the constructor in your derived class. how comes you think something different happens?

Share this post


Link to post
Share on other sites
Quote:
Original post by Clueless
The impression I got is that in that case a constructor CResource( std::string filename ); would be called ... but CResource() isn't.

Is CResource( std::string filename ); the standard constructor in that case?
That was what I was trying to talk about ;)


If i understood correctly then no, its not a default constructor, if you want that version of CResource's constructor to be invoked insead you would do:


CLogfile::CLogfile( std::string filename )
: CResource(filename), m_stream(filename.c_str()), foo(...), bar(...) {}


Just a tip, your passing by value (a copy), pass large instances by reference or constant reference, to know when pass by reference a good huerisitc to use is "anything larger than the size of the machine's integer/pointer".


struct CResource {

std::string s;

CResource(const std::string& s_ref)
: s(s_ref) {}

};

//...

struct CLogfile : CResource {

CLogfile(const std::string& s_ref)
: CResource(s_ref) {}

};
//...

Share this post


Link to post
Share on other sites
Thanks. I guess I'll use const std::string& from now on.

But yeah ...

Quote:
If you don't call the baseclass constructor explicitly the constructor without any parameters will be called, regardless of the constructor in your derived class. how comes you think something different happens?


When I was reading about OOP that was exactly how I understood it.
However, if I don't call the standard constructor of CResource in the CLogfile constructor body like that:

ddfileio::CResource::CResource();

CMemobject(); is never called for the logfile.
I have no other explanation than the parameter list.
It seems weird to me ... that is why I started the thread.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!