Sign in to follow this  
TEUTON

return value of constructor

Recommended Posts

TEUTON    100
Every book says that constructor does not have a return type not even void but it never explains why(as far as books which I have read). can anyone plz explain why constructor dos not have a return type.

Share this post


Link to post
Share on other sites
viscerante    130
The purpose of a constructor is just to set the memory aside for the object of the new type you create. Besides the initialization stuff you may choose to do inside the function it doesn't effect anything outside the class so a return type is actually pointless. Other than that I would have to say it was just how the language was created.

Vis.

Share this post


Link to post
Share on other sites
Conner McCloud    1135
Because it isn't a real function. Most of the time, you never even call it, it just gets called when the time comes.

As to why it shouldn't have a return value anyhow, what would it return? Most everything is excluded because you don't have access to it. For instance, what happens to the return value when you call new? It just vanishes...and if you don't have access to it, what good is it? The only remaining option is to return the constructed object...but you already have the constructed object, so what good is that? Really, having a return value at all is illogical.

CM

Share this post


Link to post
Share on other sites
Way Walker    745
Quote:
Original post by Conner McCloud
Really, having a return value at all is illogical.


Which is why "void" was added to the language. I was going to add a response similar to yours, but then I thought "Why not make it a function returning void?".

I've never had to overload new so I don't know anything about doing it, so I wonder if returning a value could be useful in overloading new. Is there any situation it might be useful? (Even if it's something like "fewer temporary variables" or "less typing")

Probably best answer is "it isn't a real function". I've never seen an initializer list on any other "function".

Share this post


Link to post
Share on other sites
Conner McCloud    1135
Quote:
Original post by Way Walker
Which is why "void" was added to the language. I was going to add a response similar to yours, but then I thought "Why not make it a function returning void?".

...

Probably best answer is "it isn't a real function". I've never seen an initializer list on any other "function".

If it were a function returning void, that would suggest you could make it a function returning int. But you can't, so you might as well treat it like a special function from the ground up.
Quote:

I've never had to overload new so I don't know anything about doing it, so I wonder if returning a value could be useful in overloading new. Is there any situation it might be useful? (Even if it's something like "fewer temporary variables" or "less typing")

I seriously doubt it. For instance...when you overload operator new, you don't call the constructor. The system takes care of that for you. I think one would be justified in saying that a user never directly calls a constructor, they simply create objects and the constructors get called at the appropriate time. With this in mind, the compiler is the only thing that'll care if the constructor returns a value or not...and if it did, the compiler can just stealth in whatever return value it wants.

CM

Share this post


Link to post
Share on other sites
TEUTON    100
My question was related to C++ constructors...but I just read about Java constructors( I guess its the same concept both in C++ and Java)...In the book it is written constructor can't have a return type not even void because it has an implcit return type of class. Is that true.

Share this post


Link to post
Share on other sites
Adam Hamilton    271
I don't see any use in a return type at all. You shouldn't be doing anything in a constructor that could cause an error.

That being said, if you do decide to do something like open a file for instance, you could always set a flag and overload the bool operator so you can do this


class Foo
{
private:
bool error_flag;

public:
Foo(char* file); // Sets error flag on fail

operator bool() { return error_flag; }
};

void SomeFunction()
{
Foo bar("Wha.txt");

if (bar)
{
cout << "Could not open Wha.txt" << endl;
}
}




Share this post


Link to post
Share on other sites
Quote:
Original post by Adam Hamilton
I don't see any use in a return type at all. You shouldn't be doing anything in a constructor that could cause an error.


Just a precision: you can generate errors in a constructor but since you can't return them to the caller, the best way to signal them is to throw an exception (@TEUTON: don't be afraid of that word ;)).

Quote:
Original post by Adam Hamilton
That being said, if you do decide to do something like open a file for instance, you could always set a flag and overload the bool operator so you can do this


I strongly encourage you to never ever overload the bool casting operator unless your type relates to a boolean (or to any other fundamental type). It can have nasty side effect that won't be easily spot during runtime and that may introduce very subtil bugs in your program when not used correctly (and believe me, with all this nasty automatic conversions everywhere, you wont' be able to use it correctly [smile])

But you are right: storing the error in a bool is is also another possibility, but it requires you to check for the existence of an error.

Anyway, it is still better to move all the code that might fail in anotehr class method - since this new method will be able to return an error code.

Regards,

Share this post


Link to post
Share on other sites
Programmer16    2321
Quote:
Original post by Conner McCloud
I think one would be justified in saying that a user never directly calls a constructor, they simply create objects and the constructors get called at the appropriate time.


I agree with everything you said except this line. What about:


class Base
{
int* m_pData;
public:
Base(int nAmount)
{
m_pData = new int[nAmount];
}

void Release()
{
delete [] m_pData;
}
};

class Derived : public Base
{
public:
Derived() : Base(10)
{
// Create a default amount of 10
Base(10);
}

Derived(int nAmount)
{
Base(nAmount);
}
};

// And just in case you were talking about calling just the classe's
// constructor. Wouldn't the following be directly calling it?
Derived MyDerived(21);




EDIT: I changed my source code as to not confuse anybody or to confuse them more, whichevere.

[Edited by - Programmer16 on March 15, 2006 10:30:37 AM]

Share this post


Link to post
Share on other sites
taby    1265
Quote:
Original post by Conner McCloud
I think one would be justified in saying that a user never directly calls a constructor, they simply create objects and the constructors get called at the appropriate time.


Using placement new to create objects/arrays from a pre-allocated memory buffer is the perfect reason to call the constructor manually. It's really the quickest and cleanest way I know to be able to construct an array of objects using any number (and combination) of constructors to initialize the data.

C++ FAQ Lite -- section 11.10

Share this post


Link to post
Share on other sites
Conner McCloud    1135
Quote:
Original post by Programmer16
Quote:
Original post by Conner McCloud
I think one would be justified in saying that a user never directly calls a constructor, they simply create objects and the constructors get called at the appropriate time.


I agree with everything you said except this line. What about:

*** Source Snippet Removed ***

I was just trying to prove a point, it really doesn't matter.

CM

Share this post


Link to post
Share on other sites
Adam Hamilton    271
Programmer16, I have made a correction to your code


class Base
{
int* m_pData;
public:
Base(int nAmount)
{
m_pData = new int[nAmount]; // What happens if you have no memory
// You need to make sure that you are aware
}
};

class Derived : Base
{
public:
Derived() : Base (10) // This is how you call a parents constructor
{
}

Derived(int nAmount) : Base (nAmount)
{
}
};

// And just in case you were talking about calling just the classe's
// constructor. Wouldn't the following be directly calling it?
Derived MyDerived(21);




Share this post


Link to post
Share on other sites
Programmer16    2321
Quote:
Original post by Adam Hamilton
Programmer16, I have made a correction to your code

*** Source Snippet Removed ***


While technically you are correct, since my code didn't work as it is, but I had made a mistake. I forgot to add a default constructor. If I had done so, my code would work.

@ Conner McCloud: Sorry, I wasn't trying to be rude or anything.

Share this post


Link to post
Share on other sites
Conner McCloud    1135
Quote:
Original post by Programmer16
@ Conner McCloud: Sorry, I wasn't trying to be rude or anything.

No worries, I didn't take it as rude. I just don't feel like justifying my position. Too late for that [grin]

CM

Share this post


Link to post
Share on other sites
Enigma    1410
Quote:
Original post by Programmer16
While technically you are correct, since my code didn't work as it is, but I had made a mistake. I forgot to add a default constructor. If I had done so, my code would work.

It would have worked, but would still have created local variables of type Base, not called the base-class constructor with a parameter.

Quote:
Original post by taby
Using placement new to create objects/arrays from a pre-allocated memory buffer is the perfect reason to call the constructor manually. It's really the quickest and cleanest way I know to be able to construct an array of objects using any number (and combination) of constructors to initialize the data.

You find it quicker and cleaner to correctly construct an array in an exception-safe manner using placement new than to use vector or another standard container [wow]?

Σnigma

Share this post


Link to post
Share on other sites
taby    1265
Quote:
Original post by Enigma
You find it quicker and cleaner to correctly construct an array in an exception-safe manner using placement new than to use vector or another standard container [wow]?

Σnigma


Don't get me wrong, I rarely ever use new/delete, and have successfully replaced this method of dynamic allocation by relying on the vector's inherent contiguous data layout / address-of operator to interface with functions requiring a pointer.

Yes, one could definitely use the reserve function to preallocate the buffer, then use the [] or .at or some iterator to initialize/assign the elements by using a temporary object. I find however, that it can be extremely prohibitive in terms of CPU time to create temporary objects to initialize arrays as such.

I see your point, but I don't always find it to be the most optimal solution in terms of speed or plain code reuse -- I am the epitome of the programmer who consistently forgets what they were attempting to code only hours ago. :)

On one final note, exceptions to me are similar (but more than just) debug assertions. They should theoretically only occur in production code when there is a catastrophic system failure, like an out of memory state, or if there is a bug in the code which still needs to be resolved.

At that point, I rarely care what the behaviour of the application is. I either need to fix it and re-release the production code (if it's a bug), or ignore it completely since the system's whole state is way beyond the control of my app/myself.

Share this post


Link to post
Share on other sites
Way Walker    745
Quote:
Original post by Conner McCloud
If it were a function returning void, that would suggest you could make it a function returning int. But you can't, so you might as well treat it like a special function from the ground up.


I don't want to sound like I'm arguing for a return value, but I don't find that convincing because main() is required to return int (or something "implementation defined"). I would be interested to see the discussion (if any) the standardizing committee had on the issue.

In the end, I'm guessing it just comes down to "what makes more sense to you". Having a return value like every other function because it's still a function, or having no return value because it's unlike any other function.

Does anyone know what Cfront had the constructors return after compilation to C?

Quote:

I seriously doubt it. For instance...when you overload operator new, you don't call the constructor. The system takes care of that for you. I think one would be justified in saying that a user never directly calls a constructor, they simply create objects and the constructors get called at the appropriate time. With this in mind, the compiler is the only thing that'll care if the constructor returns a value or not...and if it did, the compiler can just stealth in whatever return value it wants.


I see, thanks for the information!

Share this post


Link to post
Share on other sites
Constructors can have outputs just as they can have inputs. One can argue about how good a programming practice that is, but the method is to use references or pointers.

object :: object ( int& Result )
{
Result = SUCCESS;
}

// or...

object :: object ( int* Result )
{
*Result = SUCCESS;
}

Share this post


Link to post
Share on other sites
Bregma    9214
Quote:
Original post by Way Walker
In the end, I'm guessing it just comes down to "what makes more sense to you". Having a return value like every other function because it's still a function, or having no return value because it's unlike any other function.


The answer is that functions can return values. Constructors and destructors are not functions. They cannot return values. It's just unfortunate that their definitions use a syntax apparently similar to that of functions. Don't confuse syntax with semantics.

Share this post


Link to post
Share on other sites
Way Walker    745
Quote:
Original post by Bregma
The answer is that functions can return values. Constructors and destructors are not functions. They cannot return values. It's just unfortunate that their definitions use a syntax apparently similar to that of functions. Don't confuse syntax with semantics.


I can think of only three ways they differ from functions:
1) No return type
2) Initializer lists
3) The user isn't supposed to normally call them directly

(3) doesn't make much of an argument, because it's just like saying "don't call free() twice in a row on the same pointer". (2) is a hack that may or may not justify adding something conceptually different. (1), well, I've already covered that.

In fact, from the C++ FAQ Lite, I see this code:
void someCode()
{
char memory[sizeof(Fred)];
void* p = memory;
Fred* f = new(p) Fred();
...
f->~Fred(); // Explicitly call the destructor for the placed object
}
which tells me that at least destructors can be called like functions. Destructors also hang out with other functions in the vtable if you declare them virtual.

They may indeed not be functions, but it seems an even subtler distinction than that between arrays and pointers.

So, you've cleared up a misunderstanding of mine (c/dtors are not functions), but that doesn't change the "heart" of the question. I'll rephrase to, "Why aren't constructors/destructors functions?"

Share this post


Link to post
Share on other sites
ZQJ    496
Look at it this way: for a stack allocated object if the constructor were allowed to fail in any way but an exception you could have an invalid object visible in your scope. An exception forces you to leave the current scope, making the object invisible from the next point of execution. Because of this, constructors really can't be allowed to fail to construct the object except in 'exceptional' circumstances, which would then call for an exception. So in case the constructor fails in a non-exceptional way the object must still be in a valid state, even if that state is some kind of dead state.

Java obviously doesn't suffer this, but they probably chose the same behaviour for two reasons: first, C++ programmers are familiar with it and second, if constructors were allowed to fail without an exception you would end up with a null pointer which you probably aren't expecting, which will then cause an exception a few lines later when you use the pointer (and the exception type will be less useful since it will be a NullPointerException rather than whatever the real failure was).

Share this post


Link to post
Share on other sites
Oluseyi    2109
The return type of calling ClassName() is ClassName. Consequently, you may consider that the return type of the constructor, which is obvious, fixed and thus unnecessary. There is no reason to mandate that you supply information that never, ever varies.

[Edit: ClassName() returns ClassName, not ClassName *. Thanks to oggialli for the catch.]

Before anyone brings it up, int main is necessary because the value must be returned to the operating system, and because before C++ was standardized it was legal to have other return types for main. There is no valid comparison here.

Constructors are not unnamed. Their identifiers are an important part of their signature, especially when you consider that, like all functions in C and C++, they can be overloaded. A more trite counter argument would be the Scope::Identifier syntax for class members indicating that constructors are named ClassName::ClassName.

That is, unless Connor has a different definition of being "unnamed."

[Edited by - Oluseyi on March 15, 2006 6:57:02 PM]

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this