a) When you call a function in C++ the compiler has to generate code to process the parameters and then jump to the code containing the function. The called function has to set up a bunch of data structures to handle things like exceptions and returning from the function. These all take space in the executable file and time to execute. If a function is small this overhead can dwarf any code actually in the function. A decent optimising compiler will do an analysis of the code and execution size of a function and if it looks like the code will be smaller and/or faster it'll dump a copy of the code for the function at the calling site.
inline
is a hangover back to the days when optimisers were a bit crap. All it does is say to the compiler "I think this is a short function that could do with inlining." In them days of yore most compilers would reply "yay, someone cares!" and
inline
the code for you and not bother checking whether it was a good idea or not. These days most compilers will usually reply "I was going to do that anyway" or "what are you? Mad? That's way too big!" and then ignore the keyword. The upshot is on modern compilers
inline
doesn't do a lot for your code - a bit like the
register
keyword.
So if I were you I wouldn't bother using it anymore. Unless you're writing template classes but that's more down to the fact that most compilers don't support the
export
keyword and another story entirely.
b) In C++
struct
is virtually the same as
class
. The only difference is that all members of a
struct
are
public
by default. One of the previous posters is talking complete rubbish - they can have ordinary member functions, virtual functions, constructors and destructors, just likes
classes
. Where you use
struct
is really a matter of style - some bodies of code use
class
for everything apart from aggregates of data (which they use
struct
for), others use
struct
for things like functors and interface classes. Experiment with different styles and see which one hits the spot for you and if you code for a living make sure you at least consider the local coding styles to avoid scaring the natives.
union
is just like
struct
with one important difference*. Every data member overlays all the others. This is great when dealing with hardware but not so great when some idiot overlays a
std::string
with an
int
. The only time you ever need a
union
is when you have a set of bits that you need to interpret in more than one manner and don't want to litter your code with casts and bitwise operations. Sometimes the code can be clearer with casts though so if you ever have to do this sort of thing make sure you try various ways and see which one looks the least confusing and surprising for the audience.
So there are three ways of declaring and defining things that behave like classes but there are differences. Admittedly the difference between
class
and
struct
are fairly minimal.
c) If you have a
class
with a single argument constructor, e.g:
class foo
{
public:
foo( int n );
};
and a function that takes an argument of type foo or
const &foo
:
void bar( foo f )
{
}
then weird things can happen. Anywhere the rest of your code wants a foo you can supply an
int
and the code will work, or at least compile:
bar( 87 );
Wherever the code expects a foo and you supply an
int
the compiler will create a temporary of class foo and initialise it with the int. Then after the statement it appears in it will destroy the temporary (unless the temporary is bound to a const reference in the scope it's created in, ho, ho, ho...).
This can be very handy if the conversion makes sense at all times (e.g. the conversion between a string literal and a std::string can make code far easier to read) but it can introduce subtle errors ("Hang on, how come I'm passing a number into that function and I'm getting code called I didn't know existed!").
For those occasions when the automatic conversion everywhere doesn't make a lot of sense you can mark single argument constructors as
explicit
. It says "If you want to use this constructor you have to do so explicitly by mentioning the name of the class." You have to code all your calls to
bar
as something like:
bar( foo( 87 ) );
Anyway, hope this lot helps. Ignore
inline
, don't sweat it about
union
- you probably won't need it, and use
explicit
to turn off automatic conversions that don't make a lot of sense.
Cheers,
Ash
*That's not strictly true - unions can't have virtual functions or static member data. They can have member functions though including constructors and destructors though.