Some general C++ questions

Started by
7 comments, last by SharkOne 19 years, 11 months ago
Hi, I''ve been coding for a little while now and I''m still wondering the same things about some specific aspects of general programming. 1) As constructor can''t return any value, I''m used to having ctors in my classes which only init members to NULL or stuff like that, and to them use a Create method which can fail. This method allows me to nest class as members in others (no pointer, theres few to no "new" in my code) and in the "Create" method of the Outter class I call the "Create" methods of the members. Is that a good way to do ? What are the pros and the cons of using pointers or using direct instances in class ? 2) What''s best for error checking ? Assert ? return values ? exceptions ? I still can''t choose the proper way to do it Thanks in advance -- SharkOne
-- SharkOne
Advertisement
1) If you have errors in your constructors, exceptions are the only way to deal with them. Anything else is evil.

2) All three have different purposes. Error codes are useful for simple things that can be dealt with right away; exceptions are good for things that are exceptional, and might need to go up a few levels before being dealt with; and asserts are for things that cannot (should not) happen, and are usually used to ensure the preconditions of a function.
1) You may want to read up on RAII (Resource Acquisition Is Initialization).
--Michael Fawcett
quote:Original post by SharkOne
As constructor can''t return any value, I''m used to having ctors in my classes which only init members to NULL or stuff like that, and to them use a Create method which can fail.
This method allows me to nest class as members in others (no pointer, theres few to no "new" in my code) and in the "Create" method of the Outter class I call the "Create" methods of the members. Is that a good way to do ? What are the pros and the cons of using pointers or using direct instances in class ?

The problem with this approach is that you risk having your object in an invalid state. The purpose of a constructor is in part to ensure that this can never happen. This is related to why you should not expose a class''s implementation, but allow manipulation only via its interface: Invalid states should never be allowed to occur.

As for pointers vs. "direct instances" for the members, it depends on what you want and what you are doing. Pointers take that one extra dereferencing, and require you to deal with memory allocation and deallocation, for which reason I think you should avoid them whenever feasible; if you need pointers, if objects should share resources, or something similar, use pointers.

By the way, the generally preferred value for null pointers in C++ is (numeric) 0, not NULL.
quote:Original post by Miserable
The problem with this approach is that you risk having your object in an invalid state. The purpose of a constructor is in part to ensure that this can never happen. This is related to why you should not expose a class''s implementation, but allow manipulation only via its interface: Invalid states should never be allowed to occur.


I don''t really see what you mean ? could you give an example ?
When you say invalid state, you mean instanciated but the call to "Created" failed ? What would you suggest then ?

quote:
By the way, the generally preferred value for null pointers in C++ is (numeric) 0, not NULL.


Why 0 instead of NULL ? NULL is generally equals to 0 or (void*)0 right ?

--
SharkOne
-- SharkOne
quote:
Why 0 instead of NULL ? NULL is generally equals to 0 or (void*)0 right ?
--
SharkOne


Because if it does equal to (void*)0, then you can''t pass NULL to a function expecting a pointer to any type because void* can''t be converted to anything without a static_cast (ugly). So to make sure your program is fully portable, type 0 or use this baby:

conststruct{template <class T>operator T*() const{return 0;}template <class C, class T>operator T C::*() const{return 0;}private:void operator&() const;} NULL;



As for #1, do as others have said: use exceptions. One of the biggest reasons they are there is to shun programmers from writing those Create() methods. For #2, use assertions to check for invariants/postconditions (Check out Thinking in C++ Vol. 2), throw exceptions in constructors and other methods where you check user input and function parameters as well as resource aquisition errors. Use return values everywhere else. Remember, exceptions are for exceptional conditions only, so don''t abuse them or performance will suffer.
quote:Original post by Miserable
quote:Original post by SharkOne
As constructor can't return any value, I'm used to having ctors in my classes which only init members to NULL or stuff like that, and to them use a Create method which can fail.
This method allows me to nest class as members in others (no pointer, theres few to no "new" in my code) and in the "Create" method of the Outter class I call the "Create" methods of the members. Is that a good way to do ? What are the pros and the cons of using pointers or using direct instances in class ?

The problem with this approach is that you risk having your object in an invalid state. The purpose of a constructor is in part to ensure that this can never happen. This is related to why you should not expose a class's implementation, but allow manipulation only via its interface: Invalid states should never be allowed to occur.


I consider initialized to null a valid state. e.g. if you write a socket wrapper, it ought to create and recreate the socket when needed. In the ctor the socket handle needs to be set to a known value that means it is uninitialized. Methods such as Connect ought to create the socket if it hasn't already been created, and close and recreate the socket if it already exist. Instances of the class you write should always be usable, but thier members do not always have to be allocated. Consider vector; initially the storage can be a pointer set to null and when push_back is called it is required to validate enough storage is available to complete the operation and allocate more storage if and when it is needed.

The only time you can really have an invalid state, is if you throw an exception and either your code or the users code is not exception safe. ...Or if you fail to initialize a pointer or handle in a ctor.

[edited by - Magmai Kai Holmlor on May 19, 2004 10:35:54 PM]
- The trade-off between price and quality does not exist in Japan. Rather, the idea that high quality brings on cost reduction is widely accepted.-- Tajima & Matsubara
no, an INVALID state means a state that violates the "invariants" of a class.

Many basic classes have no invalid states, because the class invariants are simple, any values are good ... for instance a Point class with a float x, y, z, would not have any invalid states ... cause all possible states are acceptable ... but an invalid states for a "Window" class might be that the top might be "below" the bottom, or the left to the "right" or the right value ... these are invalid states, and it might be stated somewhere that such things are prevented from occuring ... obiously, if someone calls a constructor with such a situation, you might not have to throw an exception (you might swap the values), but that depends on the feasability of such things ... another might be this:

if the class says "the GetParent() function will return the parent control or window, and may not be null" then the class is in an invalid state until the parent control / window is set ... most windowing classes don''t have such a rule, but those that do, require the parent to be passed into the constructor - so that at every possible point, the class is in a valid state ... in such a situation, if someone passed a null pointer for the parent, the construct MUST throw an exception, period.
What Xai said. For more on what I was referring to, see this interview with Stroustrup.

This topic is closed to new replies.

Advertisement