asking for an opinion from the collective wisdom here

D

Devon Null

I was simply wondering if this was a mal-formed class header:

#ifndef _items_h_
#define _items_h_

#include <iostream>
#include <string>
#include <vector>

using namespace std;

class Item
{
public:
Item( float weight = 0, bool set_can_equip = false, bool
set_can_attack = false, bool set_can_defend = false, bool set_can_drink
= false, bool set_can_eat = false, bool set_can_use = false, bool
set_is_consumable = false, bool set_is_magical = false );
//Below are the set and get functions for all variables in this
class
void set_weight( float weight ) { item_weight = weight; }
float get_weight() { return item_weight; }

void set_can_equip( bool set_can_equip ) { can_equip =
set_can_equip; }
bool get_can_equip() { return can_equip; }

void set_can_attack( bool set_can_attack ) { can_attack =
set_can_attack; }
bool get_can_attack() { return can_attack; }

void set_can_defend( bool set_can_defend ) { can_defend =
set_can_defend; }
bool get_can_defend() { return can_defend; }

void set_can_drink( bool set_can_drink ) { can_drink =
set_can_drink; }
bool get_can_drink() { return can_drink; }

void set_can_eat( bool set_can_eat ) { can_eat = set_can_eat; }
bool get_can_eat() { return can_eat; }

void set_can_use( bool set_can_use ) { can_use = set_can_use; }
bool get_can_use() { return can_use; }

void set_is_consumable( bool set_is_consumable ) { is_consumable
= set_is_consumable; }
bool get_is_consumable() { return is_consumable; }

void set_is_magical( bool set_is_magical ) { is_magical =
set_is_magical; }
bool get_is_magical() { return is_magical; }

void describe(); // simply returns description (see below)
void clear_describe(); // clears description
void add_describe( string line_to_add );
/*Line above checks to see if description is set to either
need_set or desc_cleared, and if so description.clear()
then push_back( line_to_add ), else just push_back( line_to_add)*/

private: // These are stats that will be set for every item created
string need_set; // description is initialized with this
string desc_cleared; // description will be set to this after it
has been cleared
vector<string> description; // This is to allow multi-line
descriptions
float item_weight; // These are pretty self explanatory I think
bool can_equip;
bool can_attack;
bool can_defend;
bool can_drink;
bool can_eat;
bool can_use;
bool is_consumable;
bool is_magical;
};

#endif

but as I read along I was confused over something. The above works just
fine, but I was also wondering should the constructor be this:

Item( float weight = 0, bool set_can_equip = false, bool set_can_attack
= false, bool set_can_defend = false, bool set_can_drink = false, bool
set_can_eat = false, bool set_can_use = false, bool set_is_consumable =
false, bool set_is_magical = false );

with a constructor body like this in the cpp file:

Item::Item( float weight, bool set_can_equip, bool set_can_attack, bool
set_can_defend, bool set_can_drink, bool set_can_eat, bool set_can_use )
{
item_weight = weight;
can_equip = set_can_equip;
can_attack = set_can_attack;
can_defend = set_can_defend;
can_drink = set_can_drink;
can_eat = set_can_eat;
can_use = set_can_use;
is_consumable = set_is_consumable;
is_magical = set_is_magical;
need_set = "You need to set a description here!\n";
desc_cleared = "The description has been cleared.\n";
description.clear();
description.push_back( need_set );
}

or this:

Item() : float weight( 0 ), bool can_equip( false ), bool can_attack(
false ), bool can_defend( false ), bool can_drink( false ), bool
can_eat( false ), bool can_use( false ), bool is_consumable( false ),
bool is_magical( false );

and lose the entire body of the constructor in the cpp file? I will need
to pass in parameters to override the defaults when I instantiate the
objects.

Question 1: Is this a mal-formed class header?
Question 2: Which should I use for the initialization list?

Thanks in advance.
DN
--
[there are no x's in my email]

I have the right to remain silent
(and should probably use it as much as possible)
Anything I type can and will be used against me
in a court of idiocy
I have the right to be wrong
(and probably am)
If I can not furnish my own wrongness
I'm sure someone will provide it for me.
 
R

red floyd

Devon said:
I was simply wondering if this was a mal-formed class header:

#ifndef _items_h_
#define _items_h_

Yes, you are malformed right here. Per the Standard, any identifier
with a leading underscore is reserved to the implementation in the
global namespace. _items_h_ is in the global namespace.
 
D

Daniel T.

Devon Null said:
I was wondering should the constructor be this:

Item( float weight = 0, bool set_can_equip = false, bool set_can_attack
= false, bool set_can_defend = false, bool set_can_drink = false, bool
set_can_eat = false, bool set_can_use = false, bool set_is_consumable =
false, bool set_is_magical = false );

with a constructor body like this in the cpp file:

Item::Item( float weight, bool set_can_equip, bool set_can_attack, bool
set_can_defend, bool set_can_drink, bool set_can_eat, bool set_can_use )
{
item_weight = weight;
can_equip = set_can_equip;
can_attack = set_can_attack;
can_defend = set_can_defend;
can_drink = set_can_drink;
can_eat = set_can_eat;
can_use = set_can_use;
is_consumable = set_is_consumable;
is_magical = set_is_magical;
need_set = "You need to set a description here!\n";
desc_cleared = "The description has been cleared.\n";
description.clear();
description.push_back( need_set );
}

or this:

Item() : float weight( 0 ), bool can_equip( false ), bool can_attack(
false ), bool can_defend( false ), bool can_drink( false ), bool
can_eat( false ), bool can_use( false ), bool is_consumable( false ),
bool is_magical( false );

and lose the entire body of the constructor in the cpp file? I will need
to pass in parameters to override the defaults when I instantiate the
objects.

You can't lose the entire body of the constructor. However to answer the
underlying question, you should use the no argument constructor and just
initialize all the variables.

Item::Item() :
weight( 0 ),
can_equip( false ),
can_attack( false ),
can_defend( false ),
can_drink( false ),
can_eat( false ),
can_use( false ),
is_consumable( false ),
is_magical( false )
{ }

At some point you will realize that your code is full of blocks that
check the various flags in this class and behave differently depending
on the setting of the flag. Then when you learn about polymorphism, you
will start writing better classes.
 
T

terminator

You can't lose the entire body of the constructor. However to answer the
underlying question, you should use the no argument constructor and just
initialize all the variables.

Item::Item() :
weight( 0 ),
can_equip( false ),
can_attack( false ),
can_defend( false ),
can_drink( false ),
can_eat( false ),
can_use( false ),
is_consumable( false ),
is_magical( false )
{ }

At some point you will realize that your code is full of blocks that
check the various flags in this class and behave differently depending
on the setting of the flag. Then when you learn about polymorphism, you
will start writing better classes.- Hide quoted text -

- Show quoted text -

both forms can be used for ctors but the later is better when const
data members exist and the former is needed when members have to be
assigned assciated values:

int f(int,int);//A big function

class A{
public:
const int m;
int n,p;
A(int i,int j):
p(0),
m(f(i,j))//const must be initialized here.
{n=m;};/*if n is initailized in the initializer list f is called
twice which time expensive.*/
};
 
T

terminator

Yes, you are malformed right here. Per the Standard, any identifier
with a leading underscore is reserved to the implementation in the
global namespace. _items_h_ is in the global namespace.

what is wrong with it?
This is an avanced technique used in proffesional libraries to prevent
probable linker errors generated by repetition.It also decreases
compile time.

regards,
FM
 
J

Jerry Coffin

what is wrong with it?
This is an avanced technique used in proffesional libraries to prevent
probable linker errors generated by repetition.It also decreases
compile time.

As he already pointed out, what's wrong is the _name_ you've used. The
technique is perfectly legitimate and allowable, but the name you've
used is not. If you change to something like:

#ifndef ITEMS_H_INCLUDED
#define ITEMS_H_INLCUDED

you'll be fine, because this name does NOT have a leading underscore
like the one you used.
 
R

Robert Bauck Hamar

terminator said:
what is wrong with it?

_items_h_ starts with an underscore.
This is an avanced technique used in proffesional libraries to prevent
probable linker errors generated by repetition.It also decreases
compile time.

Yes, but there are two rules:

1. Never use a name starting with an underscore in the global namespace.
2. Never use a name starting with an underscore followed by a capital
letter, or a name containing __ in _any_ namespace.

Include guards are very handy, but name them properly.
 
D

Daniel T.

terminator said:
both forms can be used for ctors but the later is better when const
data members exist and the former is needed when members have to be
assigned assciated values:

int f(int,int);//A big function

class A{
public:
const int m;
int n,p;
A(int i,int j):
p(0),
m(f(i,j))//const must be initialized here.
{n=m;};/*if n is initailized in the initializer list f is called
twice which time expensive.*/
};

I try to avoid such micro-optimizations unless profiling has shown that
they are necessary. For this specific case, if the function has no side
effects, I expect the compiler would be smart enough to cache the return
value for the second use.
 
P

Pete Becker

terminator said:
what is wrong with it?
This is an avanced technique used in proffesional libraries to prevent
probable linker errors generated by repetition.It also decreases
compile time.

It's not at all advanced. Every header should have include guards. The
problem it solves is repeating definitions at compile time, which
produces compile-time errors, not linker errors. The problem with this
particular example, as has been pointed out in several other messages,
is the name of the guard.

--

-- Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com)
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." (www.petebecker.com/tr1book)
 
T

terminator

I try to avoid such micro-optimizations unless profiling has shown that
they are necessary. For this specific case, if the function has no side
effects, I expect the compiler would be smart enough to cache the return
value for the second use.- Hide quoted text -

- Show quoted text -

you pointed to the side effects ;that is exactly what I mean ,and
since there is no way for the compiler to guess the existance of such
side effects it must not censor your code-or cache the value as you
wrote.

regards
 
T

terminator

_items_h_ starts with an underscore.


Yes, but there are two rules:

1. Never use a name starting with an underscore in the global namespace.
2. Never use a name starting with an underscore followed by a capital
letter, or a name containing __ in _any_ namespace.

Include guards are very handy, but name them properly.

header guards from mainstream libraries that I have faced , all have
underscored guards. In fact since gaurds are not intended to be used
more than a few times - in header related stuff only - , they are the
best candidates for dirty names .This way good names can be reserved
for more important things which are supposed to be introduced in
global namespace.

regards
 
J

James Kanze

_items_h_ starts with an underscore.
Yes, but there are two rules:
1. Never use a name starting with an underscore in the global namespace.
2. Never use a name starting with an underscore followed by a capital
letter, or a name containing __ in _any_ namespace.
Include guards are very handy, but name them properly.
[/QUOTE]
header guards from mainstream libraries that I have faced , all have
underscored guards. In fact since gaurds are not intended to be used
more than a few times - in header related stuff only - , they are the
best candidates for dirty names .This way good names can be reserved
for more important things which are supposed to be introduced in
global namespace.

Unless the library is part of the implementation, such names are
illegal, and result in undefined behavior.

Many basic libraries (e.g. Posix) do consider themselves "part
of the implementation". Third party libraries which don't,
however, are in error if they use such names. Or maybe the
fact that they use such names is a signal that they do consider
themselves as an extention of the implementation. (At any rate,
I tend to consider things like the data base library as "part of
the implementation.")
 
G

Gavin Deane

header guards from mainstream libraries that I have faced , all have
underscored guards. In fact since gaurds are not intended to be used
more than a few times - in header related stuff only - , they are the
best candidates for dirty names .This way good names can be reserved
for more important things which are supposed to be introduced in
global namespace.

The point is not whether the names are sufficiently dirty to avoid
name collisions. The point is that, unless these libraries are part of
the implementation, they are invading the "namespace" set aside by the
standard for the sole use of the implementation, and that is illegal.

Since include guards are #define'd macro names, the best way to avoid
name clashes between them and the rest of your code is whatever you
normally do to prevent macro names clashing with code. The most common
example I've seen is that macro names (including include guards) are
always ALL_CAPS and everything else is never ALL_CAPS, but any naming
convention that creates a separate "namespace" for macros is
sufficient (as long as it doesn't invade the implementation's
namespace).

And, of course, you can have naming conventions within that to protect
include guard names from other macros if you want. For example,
include guards always ending in _H and other macros never ending in
_H. But again, any naming convention works as long as it doesn't break
the two rules above.

Gavin Deane
 
T

terminator

Unless the library is part of the implementation, such names are
illegal, and result in undefined behavior.

Many basic libraries (e.g. Posix) do consider themselves "part
of the implementation". Third party libraries which don't,
however, are in error if they use such names. Or maybe the
fact that they use such names is a signal that they do consider
themselves as an extention of the implementation. (At any rate,
I tend to consider things like the data base library as "part of
the implementation.")

--
James Kanze (GABI Software) email:[email protected]
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34- Hide quoted text -

- Show quoted text -

please inform me of the disadvantages of having such form of
guards.These are possible combinations of legal characters ,why not to
device them?? are they reserved for none-portable issues only?

regards,
FM
 
G

Gavin Deane

please inform me of the disadvantages of having such form of
guards.These are possible combinations of legal characters ,why not to
device them?? are they reserved for none-portable issues only?

Please trim your posts to only include sufficient context to make the
post comprehensible. And please don't quote signatures, or the "quoted
text" garbage that Google inserts. Thanks.

Your answer is in the discussion above. Using names reserved to the
implementation results in undefined behaviour. That's it. That's all
the disadvantage you need. That statement alone should be sufficient
reason for you to avoid such names.

comp.lang.c++ discusses *what* is in the C++ standard. As far as
*what* goes, that's all there is to it. However, you are asking *why*
- and there is generally a reason for these things. One could
speculate in this case that the rules above give implementors a
separate "namespace" they can use. If they only use the names that are
reserved to them, and you never use the names that are reserved to
them, you can be confident that you won't suffer name clashes with the
implementation. If one didn't want to speculate, comp.std.c++ is a
more topical place to discuss *why* the C++ standard is the way it is.

Gavin Deane
 
J

James Kanze

please inform me of the disadvantages of having such form of
guards.

The disadvantage is that they are illegal, and using them causes
your code to have undefined behavior.
These are possible combinations of legal characters ,why not to
device them?? are they reserved for none-portable issues only?

The reason the standard bans them is precisely to give the
implememters a set of names they can use, without risk of
conflicts with your code. Thus, for example, some library
header might contain something like:

class SomeStandardClass
{
private:
int _items_h_
} ;

Now what happens if you include that library header in your
header?
 
D

Daniel T.

you pointed to the side effects ;that is exactly what I mean ,and
since there is no way for the compiler to guess the existance of
such side effects it must not censor your code-or cache the value
as you wrote.

I disagree that "there is no way for the compiler to guess the
existance of such side effects". If the function deals with only its
parameters and local variables, there is no way for it to *have* side
effects.
 
T

terminator

I disagree that "there is no way for the compiler to guess the
existance of such side effects". If the function deals with only its
parameters and local variables, there is no way for it to *have* side
effects

I have commented 'f' to be a large function whose value cannot be
deduced before excution specifically 'f' can be a random value
generating function.I would delare 'f' as 'inline' if it was a simple
value-forcastable function;this would motivate the compiler for
optimization. Moreover what I wrote is not a micro-
optimization.consider these two cases:
1. 'f' is an input function
2. 'f' is a random-return function
the return of 'f' will be different on every call in these cases.

regards,
FM
 
T

terminator

The disadvantage is that they are illegal, and using them causes
your code to have undefined behavior.

Illegal? You keep repeating this sentence.Please define illegal; I
think that must mean something syntactically wrong, but if you mean
none-std then I would humblly ask why is it none-std?

By the way thanks to everyone I have found that underscored names are
supposed to be used by implementors and others including third-party
libraries had better keep off them(it is not a must).

regards,
FM.
 
D

Daniel T.

terminator said:
I have commented 'f' to be a large function whose value cannot be
deduced before excution specifically 'f' can be a random value
generating function.I would delare 'f' as 'inline' if it was a simple
value-forcastable function;this would motivate the compiler for
optimization. Moreover what I wrote is not a micro-
optimization.consider these two cases:
1. 'f' is an input function
2. 'f' is a random-return function
the return of 'f' will be different on every call in these cases.

In that case, calling f more than once will probably change the behavior
of the program and we are in a whole different world. Your initial
comment that you are doing it because it is "time expensive" is then in
error, your not calling it twice because that would be an error
regardless of the time it takes.

If that is the case, then you could do something like this:

class A {
const int m;
int n;
public:
A( int i, int j ): m( f( i, j ) ), n( m ) { }
};

Based on your earlier post, you are under the impression that assigning
in the body of the constructor is required under certain circumstances,
I don't think that is the case.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top