Sign in to follow this  
Boder

C++ Curiosities

Recommended Posts

Boder    938
So I'm wondering. Why isn't "null" a keyword? Why don't we put semicolons at the end of functions (implementation)? How come it's so inconvenient to change a function's prototype? I have to change it in the header file, the implementation file, and everywhere that it's called. Shouldn't header guards be implemented in a less hackish way? When would you include the same file twice?

Share this post


Link to post
Share on other sites
Adam Hamilton    271
Quote:
Original post by Boder
So I'm wondering.

Why isn't "null" a keyword?

Why don't we put semicolons at the end of functions (implemenation)?

How come it's so inconvenient to change a function's prototype? I have to change it in the header file, the implementation file, and everywhere that it's called.

Shouldn't header guards be implemented in a less hackish way? When would you include the same file twice?


1. NULL is a value, values are not keywords
I think Visual C++.NET 8.0 has a keyword called nullptr
I don't see the point anyway...

2. You can put a semicolon at the end of a functions implementation if your heart desires but it isn't necessary because of the braces

3. That's what find/replace is good for. BTW. What do you mean by inconvinient? Why are you changing the names of functions in the middle of a project anyway?

4. They are... #pragma once for visual c++ compilers.

This is a situation where main.cpp will include the header1.h file twice
The header guard would detect this and subsequently not bothering with the parsing of the object class again (Slower....)

header1.h

class object
{};

header2.h
#include "object.h"
class der1 : object
{};

header3.h
#include "object.h"
class der2 : object
{};


main.cpp
#include "header2.h"
#include "header3.h"

Share this post


Link to post
Share on other sites
Drew_Benton    1861
Quote:
Original post by Adam Hamilton
1. NULL is a value, values are not keywords


What about true and false? [wink] [reference link]

I don't have an answer as to why null is not a keyword, it's more of a logical problem. For example, what would you define NULL as? It can't be 0, then you could have char x = null; , but x would not represent null since it is not a pointer. Tricky stuff like that is what makes it not I'd venture to say.

Share this post


Link to post
Share on other sites
Boder    938
Is NULL guaranteed to be defined even if you don't include stdlib.h (C and C++)?

Here is a little trick for toggling a boolean value (just saw it):

flag ^= true;

Share this post


Link to post
Share on other sites
Roboguy    794
Quote:
Original post by Boder
Why don't we put semicolons at the end of functions (implementation)?


You can but you aren't required to. You are required to for classes and structs because you can define objects (multiple object definitions are separated by commas) between the } and the ;. For example:

#include <iostream>
struct {
int operator()(int x, int y) { return x + y; }
} add;

int main() {
std::cout << add(1, 2) << std::endl; // prints 3
return 0;
}

Share this post


Link to post
Share on other sites
Way Walker    745
Quote:
Original post by Boder
Why isn't "null" a keyword?


Historical reasons. 0 is recognized as "0" for most types (floating point 0, integer 0, null pointer 0) and is false for those types (with anything else being true). In a way, 0 is the C++ word for null.

Quote:

Why don't we put semicolons at the end of functions (implementation)?


For the same reason you don't for if/else, while, namespace, etc. No ; after } is actually more consistent. The reason it's required after class, struct, and enum definitions is because you can create an instance.

class A { /* stuff... */ } a;

You now have an instance. Don't want an instance? Leave it blank. I don't know the history of when code such as:

struct A { /* stuff... */ };
struct A a;

entered C, but it's in C++ because it's in C.

Quote:

How come it's so inconvenient to change a function's prototype? I have to change it in the header file, the implementation file, and everywhere that it's called.


First, how could it be possible to change the prototype but not change everywhere it's called? I can imagine an IDE potentially replacing every call with some default for new paramters, but I'm not sure if that's very useful or not.

As for having to change it in a header and the implementation file, that's to make things easier on the compiler and, in some ways, offers more flexibility in how you design your source tree. It means the compiler doesn't have to know about or even have access to the code or binaries of libraries. All the relevant information is in the file it's currently compiling.

Quote:

Shouldn't header guards be implemented in a less hackish way? When would you include the same file twice?


See cassert for an example.


#include <iostream>

#define NDEBUG
#include <cassert>
int foo(int a) { assert(0); std::cout << "foo()\n"; }

#undef NDEBUG
#include <cassert>
int bar(int a) { assert(0); std::cout << "bar()\n"; }

int main() {
foo();
bar(); /* BOOM! */
}





So, basically, it's a lot of leftovers from C. Objective-C has a #import keyword to #include only once, but some criticise it saying that it's for the header file to decide how many times it should be able to be included.

If it all seems a bit archaic, try a younger language. (or an older language *cough* Lisp *cough*)

[Edited by - Way Walker on March 26, 2006 11:28:59 PM]

Share this post


Link to post
Share on other sites
Adam Hamilton    271
I made modifications to my original post when I saw how mean I sounded...

true and false... I have never thought of them as keywords (more like a reserved word), just something handy the compiler gives you (maybe the compiler can optimise better). I read the reference link you posted and noticed they are the only keywords that are described as values...

I still wouldn't consider it a keyword though (I'm stubborn I know) keywords make the compiler switch different states

Share this post


Link to post
Share on other sites
smitty1276    560
Because C++ is one of the most poorly designed languages to ever see such popularity. There are a zillion things about C++ that are simply retarded, but we use it anyway.

Why do initializers in a class constructor take the form varName(value)? Why not a list of expressions to be evaluated? Why is that the only place where that syntax appears in the entire language? Becuase it's a horrid language from a design perspective, that's why.

C++ is one big hack.

(BTW, I'm not trying to start a flame war, so nobody get mad.)

Share this post


Link to post
Share on other sites
Boder    938
I looked into initialization lists because I didn't quite understand what you were suggestion they be replaced with.

It looks like the main drawback is that you can't do error-checking on the arguments that were given to the constructor.

How would the "list of expressions to be evaluated look"? Would there be two {} {} sections?

Share this post


Link to post
Share on other sites
smitty1276    560
Quote:
Original post by Boder
How would the "list of expressions to be evaluated look"? Would there be two {} {} sections?


The "list of expressions to be evaluated" would look like valid c++ code (whereas the current incarnation does not). The for statement takes (expr list; bool expr; expr list), for example. My point with the initializers is that they were just kinda thrown in and have no relation at all to any other syntax in the C++ language. Assigning a value to a variable shouldn't look like a function call, unless that is what assigning a value to a variable looks like in the language.

The entire language was just sort of slapped together. I wasn't kidding when I said it was a hack. I don't mean it in a bad way (beyond the intrinsic badness of it, at least). It originated in a desire to coerce a non-OO language to work with classes, etc., without sacrificing backward compatibility. It's a recipe for disaster. [grin]



Share this post


Link to post
Share on other sites
Way Walker    745
Quote:
Original post by Boder
I looked into initialization lists because I didn't quite understand what you were suggestion they be replaced with.

It looks like the main drawback is that you can't do error-checking on the arguments that were given to the constructor.

How would the "list of expressions to be evaluated look"? Would there be two {} {} sections?


Why not? Call them "initializer" and "constructor" sections. If you extend it to functions in general, it could make RAII a more integrated and explicit part of the language. (Of coruse, then you're starting to look like C's "all variables at the start of a function" which was removed, for the most part, because of constructors)

Share this post


Link to post
Share on other sites
Washu    7829
Quote:
Original post by Boder
So I'm wondering.

Why isn't "null" a keyword?

Perhaps you should look at: A name for the null pointer: nullptr
Quote:

Why don't we put semicolons at the end of functions (implementation)?

Why? The closing brace is sufficient to indicate the end of the function, or any other scope.
Quote:

How come it's so inconvenient to change a function's prototype? I have to change it in the header file, the implementation file, and everywhere that it's called.

This is why you should use refactoring tools, they tend to handle that for you, and are a lot smarter than find and replace (which is indescriminant).
Quote:

Shouldn't header guards be implemented in a less hackish way? When would you include the same file twice?

Nothing hackish about it, although it can be ugly. You can also use #pragma once on certain compilers, however it is not a standard thing, and thus is not supported by all compilers (such is the nature of pragmas).

Share this post


Link to post
Share on other sites
Quote:
Original post by Washu
Why? The closing brace is sufficient to indicate the end of the function, or any other scope.


True, which is why needing a ; at the end of a class definition annoys me a bit -_-.

Share this post


Link to post
Share on other sites
HQ-SOFT    151
Quote:
Original post by smitty1276
Why do initializers in a class constructor take the form varName(value)? Why not a list of expressions to be evaluated? Why is that the only place where that syntax appears in the entire language? Becuase it's a horrid language from a design perspective, that's why.


The varName(value) syntax can be used when initializing a variable. For example:


int main()
{
int i(0);
int j = 0;
printf("%d %d \n", i, j);
return (0);
}



Either way is perfectly valid C++.

-HQ.

Share this post


Link to post
Share on other sites
Boder    938
When defining functions for a namespace, I usually do something like so

namespace MySpace
{

func1() {}
func2() {}

}


But for classes it works differently.

class MySpace
{

func1() {}
func2() {}

}


I don't think that will compile. So I write


MySpace::func1() {}
MySpace::func2() {}


Any tips to avoid the extra typing?

Share this post


Link to post
Share on other sites
Fruny    1658
Quote:
Original post by smitty1276
Because C++ is one of the most poorly designed languages to ever see such popularity. There are a zillion things about C++ that are simply retarded, but we use it anyway.

...

C++ is one big hack.


The same can be said of the x86 architecture, which has seen massive adoption where other arguably better designs have failed.

Share this post


Link to post
Share on other sites
Boder    938
Don't you think it would be a good idea to define class methods like so

class MyClass
{

func1() {}
func2() {}

}


But not in the header file.

Share this post


Link to post
Share on other sites
ZQJ    496
Quote:
Original post by Boder
Don't you think it would be a good idea to define class methods like so

class MyClass
{

func1() {}
func2() {}

}


But not in the header file.


Newer languages like Java and D unify the definition and declaration sections to make the programmer's life easier but it needs a cleverer compiler to search multiple files for the extra definitions. C++ wasn't built like that - it was meant to be like C where the compiler can get everything it needs to know from just the preprocessed input, which is why definition and declaration are separate because the declaration is necessary to call a function/allocate a class instance, but the definition isn't.

On the subject of initialiser lists, how do you want it to work? In C++ if an object is accessable it must have been constructed already and the only way to handle this in a class constructor for its members is to construct them before the start of the constructor itself, so if you want to be able to call non-default constructors initialiser lists are necessary.

As for x86 and C++ being big hacks built on little hacks, yep, they are, but it's about the best we've got at the moment, and I for one am hoping they'll get replaced sooner rather than later (I can't see anything that'll replace C++ soon though, as for x86, x86-64 might do something).

Share this post


Link to post
Share on other sites
NotAYakk    876
Quote:
Original post by Boder
So I'm wondering.

Why isn't "null" a keyword?


C had the pseudo-keyword NULL that evaluates to 0.

However, "null" was in use by lots of C code, and using terms that exist in lots of existing code as keywords is rude.

They should have added a nullptr keyword, but they didn't. I expect it to be in the next version of the C++ standard.

Quote:
Why don't we put semicolons at the end of functions (implementation)?


Semicolons serve three purpsoses.
1> Statement terminators.
2> variable declairation terminators.
3> for(;;) sub-statement seperators.

Functions are not variable declairations.

Most compilers accept naked ;s, so placing one at the end of a function doesn't hurt.

Quote:
How come it's so inconvenient to change a function's prototype? I have to change it in the header file, the implementation file, and everywhere that it's called.


You only have to change it wherever it is called if your new prototype is incompatable with the old prototype. And if it is incompatable, you should be looking at everwhere it is called in any case!

Quote:
Shouldn't header guards be implemented in a less hackish way? When would you include the same file twice?


The C preprocessor "solved" the problem in a flexable way, so people didn't resolve to resolve the problem. ;)

Sometimes people use header files as "macro programs", defining tokens before hand to change the meaning of #include "header.h".

Reasons to do this have included:
1> #define FORWARD_DECL
#include ...
#undef FORWARD_DECL
to get the forward declairations from a bunch of header files.

2> Primitive generic code tricks. Having a math library that works on doubles or floats or ints depending on what preprocessor tokens you define before #including it.

HTH.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
Quote:
Original post by NotAYakk
1> #define FORWARD_DECL
#include ...
#undef FORWARD_DECL
to get the forward declairations from a bunch of header files.

2> Primitive generic code tricks. Having a math library that works on doubles or floats or ints depending on what preprocessor tokens you define before #including it.


Another popular thing to do is:

/*************/
/* globals.h */
/*************/
#ifndef H_GLOBALS
#define H_GLOBALS

#undef MY_EXTERN
#ifdef GLOBALS_ONCE
#define MY_EXTERN
#else
#define MY_EXTERN extern
#endif

MY_EXTERN int g_int;
MY_EXTERN double g_double;
/* etc... */

#endif


/*************/
/* globals.c */
/*************/
#define GLOBALS_ONCE
#include "globals.h"


/**********/
/* main.c */
/**********/
#include "globals.h"

int main() {
/* Use g_int, g_double, etc... */
return 0;
}


Unless that's what you were meaning by your "forward declare" trick?

Share this post


Link to post
Share on other sites
Simian Man    1022
Quote:
Original post by smitty1276
The "list of expressions to be evaluated" would look like valid c++ code (whereas the current incarnation does not). The for statement takes (expr list; bool expr; expr list), for example. My point with the initializers is that they were just kinda thrown in and have no relation at all to any other syntax in the C++ language. Assigning a value to a variable shouldn't look like a function call, unless that is what assigning a value to a variable looks like in the language.


It looks like a constructor call though. You do

MyClass object("data", 1, false);

So why not:

int number(7);

Seems pretty uniform to me...

Share this post


Link to post
Share on other sites
Rebooted    612
Quote:
Original post by smitty1276
The "list of expressions to be evaluated" would look like valid c++ code (whereas the current incarnation does not). The for statement takes (expr list; bool expr; expr list), for example. My point with the initializers is that they were just kinda thrown in and have no relation at all to any other syntax in the C++ language. Assigning a value to a variable shouldn't look like a function call, unless that is what assigning a value to a variable looks like in the language.

You arn't assigning a value to a variable. You are constructing a variable. And thats what constructing a variable looks like.

Share this post


Link to post
Share on other sites
cypherx    204
C++ is full of clumsy design choices. Consider the half-dozen meanings for the const keyword, "=0" used to designate pure virtual methods, virtual inheritance, the interaction of function overloading and template specialization.

C++ is a jack-of-all trades language that makes lots of simple things hard and takes way too long to learn well. Still, it's the only game in town if you want both high level programming constructs (object-oriented, generic programming) and low-level control (manual memory management, pointer fiddling, etc..)

-Alex

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
Quote:
Original post by cypherx
C++ is a jack-of-all trades language that makes lots of simple things hard and takes way too long to learn well. Still, it's the only game in town if you want both high level programming constructs (object-oriented, generic programming) and low-level control (manual memory management, pointer fiddling, etc..)


So, basically, C++ let's you have your cake and eat it, too, so long as you don't mind a fresh-from-the-oven pan on your lap and that the frosting is laced with a triple dose of ex-lax.

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