Noob to C++, trying to get syntax, etc.

R

Rich Grise

I think I've finally found a tutorial that can get me started:

http://www.zib.de/Visual/people/mueller/Course/Tutorial/tutorial.html

and I've been lurking for awhile as well. What happened is, I've
been playing with Qt in KDE on a Slackware 10.0 system, and following
their cookbook exercises, and everything's working, and I have no
clue what the code is doing, i.e.. how do I connect my brain to the
ascii in the files to the stuff on the screen simultaneously? And
I got to a point where I knew I need to learn basic C++.

So, I see this in the tutorial, which is a construct I've seen in
the NG (he's talking about linked lists):
--------------
list_handle_t<Apple> list1; /* a list of apples */
list_handle_t<Car> list2; /* a list of cars */
--------------
So far, he's been using pseudocode, fair enough, I first learned to
copy-n-paste C hundreds of years ago. But I wonder - in this particular
example, is this guy speaking "real C++"? IOW, would the above
work in a real program? I ask because I've seen it (or very similar) in
examples in the NG, but didn't have the referent. If so, I've just learned
something which means the day's complete and it's time to get out the
beer. ;-)

Thanks,
Rich
 
P

Phlip

Rich said:
I think I've finally found a tutorial that can get me started:

http://www.zib.de/Visual/people/mueller/Course/Tutorial/tutorial.html

Have you written a "hello world" program yet? And always learn C++ from more
than two tutorials, at the same time. Try /Accelerated C++/ by Koenig and
Moo.
So, I see this in the tutorial, which is a construct I've seen in
the NG (he's talking about linked lists):

Unfortunately, yes. They are templates. (But the comments could use //
instead of /* */.)

The following dissertation intends to help people read C++, not write new
code. You would do me a major favor if you read the following and told me
where (if anywhere) you get lost.

Bjarne Stroustrup invented C++ to provide the popular but low-level C
language with the keywords virtual, template and operator. Those enable
Object Oriented techniques with minimal runtime overhead. C is "portable
assembler", and C++ is "portable OO assembler".

C++ in a Nutshell
C++ is a statically typed language. It has no latent "Object" base class to
supply default behaviors to all objects. C++ supports Object Oriented
techniques, but not everything in C++ is an object.

All C++ entities have a declaration and a definition. C++ uses a compiling
and linking system that compiles many declarations and a few definitions
together into one "object code file". Then many of these link together to
form a complete program.

Only source statements compiled below a declaration can use its identifiers.
Developers can declare and define classes and functions simultaneously (the
preferred way), or they can move declarations to separate files. This Case
Study will show tests followed by the code that passes them, but that code,
or its declarations, must in source appear above their tests.

C++ supports very large Object Oriented applications when modules typesafely
compile remote modules' interface declarations, without the burden of
recompiling their implementation definitions.

Language Law: C++ supports both methods and modules, but has no single
explicit keyword for either. Programmers assemble methods and modules from
primitive facilities. Roughly speaking, a method is a virtual class member
function, and a module is a translation unit, typically based on compiling
one .cpp file.

The command to import a module's declarations is #include, and the command
to import an identifier from that module is using. The Hello World project
for C++ is:

#include <iostream> // copy in declarations, and some definitions

using std::cout; // meaning Console OUTput
using std::endl; // meaning END of Line

int main()
{
cout << "Hello World!" << endl;
return 0;
}

The function main() returns a 0, which tells the environment that this
program ran without errors.

The number 0 has a weak type, usually integer. All C++ functions declare
their return type, or they declare void to return nothing.

In my Uncommon Style Guide, functions' return types are less important than
the functions' names. Indenting the return values, like this...

int
main()
{
....
}

....cleans the left column, so scanning it reveals only function names. This
style becomes very easy to read - especially as function types get long.

Applying the Object Method Refactor to the Hello World application yields
this class:

using std::eek:stream;

class
WorldGreeter
{
public:

void
greet(ostream &out)
{
out << "Hello World!" << endl;
}
};

int
main()
{
WorldGreeter aGreeter;
aGreeter.greet(cout);
return 0;
}

The console stream object, cout, passes into greet() by reference. greet()
takes a reference (&) to an ostream, which is one of cout's classes' base
classes. ostream and many classes derived from it use << to insert data into
their streams.

This stream insertion concept makes the following chapters easier to
understand. C++ permits operator overloading, meaning programmers specify
what some operators do. The operator <<, applied to integers, shifts their
bits, so 2 << 3 == 16.

Shifting objects makes no sense, so << is free to overload for stream
objects. Refactoring our "Hello World" project, one more time, illustrates
this principle:

class
WorldGreeter
{
public:

void
greet(ostream &out) const
{
out << "Hello World!";
}
};

ostream &
operator<<(ostream &out, WorldGreeter const &aGreeter)
{
aGreeter.greet(out);
return out;
}

int
main()
{
WorldGreeter aGreeter;
cout << aGreeter << endl;
return 0;
}

The ability to insert any object, as text, into a stream, is more than
syntactic sugar. When templates and macros call operator<<, they can use any
argument type that has such an operator. The Standard Library defines
operator<< for all the primitive data types-int, double, std::string,
etc.-and programmers define one for each object they need. Note the above
operator<< is part of WorldGreeter's interface, but is not a member of the
WorldGreeter class. C++ types work in mysterious ways.

In C++, classes are not objects. This makes passing a class into a method,
as a parameter, problematic. C++ compiles all class details into various
opcodes, wherever they occur, so a running C++ program has no single entity
to refer to as a class.

C++ programs use templates to merge types. Each template instantiation
expands a class-like definition into a set of classes, each varying by some
type or integer.

This example upgrades our WorldGreeter example one more useless time. This
version converts WorldGreeter into a template, parameterized by an integer
that sets how ecstatically the two instantiated classes, WorldGreeter<2> and
WorldGreeter<3>, greet the world:

template<int count>
class
WorldGreeter
{
public:

void
greet(ostream &out) const
{
for(int x = 0; x < count; ++x)
out << "Hello World! ";
}
};

ostream &
operator<<(ostream &out, WorldGreeter<2> const &aGreeter)
{
aGreeter.greet(out);
return out;
}

ostream &
operator<<(ostream &out, WorldGreeter<3> const &aGreeter)
{
aGreeter.greet(out);
return out;
}

int
main()
{
WorldGreeter<2> aGreeter2;
WorldGreeter<3> aGreeter3;
cout << aGreeter2 << aGreeter3 << endl;
return 0;
}

When templates parameterize based on types, they can create new classes that
specialize to manage any of a range of details for each type. For example,
the C++ Standard Library provides a template called std::basic_string<>.
Supplying this with a character type provides string types of any needed
width:

namespace std {
typedef basic_string<char> string; // 8-bits
typedef basic_string<wchar_t> wstring; // 16-bits
}

The keyword namespace is one of the language primitives that collude to
create modules. Identifiers from the C++ Standard Library often begin with
std::, to distinguish their source module. A namespace is a prefix (std)
that must precede all uses of identifiers declared within their scope
(string, wstring). The scope operator, ::, links them.

The keyword typedef converts a type declaration into a single name. Here, it
instantiates templates into their target classes. The sample creates the
class std::string, to contain 8-bit character strings, and the class
std::wstring, to contain 16-bit character strings.

To avoid writing std:: all over the place, insert a namespace's identifiers
into your scope with a few using declarations:

#include <string>
#include <sstream>
#include <iostream>

using std::string;
using std::stringstream;
using std::cout; // console output stream
using std::endl; // line feed object

C++ macros provide some important features above the level of the actual
language. Here's a macro, using some of those stream things:

#define db(x_) cout << (x_) << endl

Macros perform simple text substitutions directly on raw C++ source, before
the type-sensitive phase of compilation. Put another way, if you can't think
how to do something directly, you can often write a macro to do it. (Those
of you who know C++ well enough to abhor that advice are requested to
attempt the following techniques using any other C++ facilities.)

Below that macro, if you write db(5), you get cout << (5) << endl. A rote
text substitution, without awareness of 5's meaning. It's just raw text. The
cout << (5) then inserts 5, typesafely, into the console stream, so you can
see it on a command prompt. The << endl part delivers a linefeed, and
flushes that console stream's buffer.

So far, a small templated function could have performed the same feat. Use
macros for the stringerizer operator, #:

#define db(x_) cout << #x_ ": " << (x_) << endl

"db" stands for debug. If q == 5, and if q is suspicious, we can trace q's
name and value to the console using db(q). That outputs "q: 5\n". This macro
makes our trace statement easy to write. The equivalent printf() statement
(if q were only an integer) would be printf("q: %i\n", q). Our statement
works for any type that supports an operator<<, and it outputs the name of q
automatically, using #x_.

Suppose a long program run emitted a strange message, complaining about some
obscure variable named q. Rapidly finding the line of code containing that
db(q) call relieves stress:

#define db(x_) do { \
cout << __FILE__ << "(" << __LINE__ << ") : " \
#x_ " = " << x_ << endl; } while (false)

That emits, roughly, "C:\path\source.cpp(99) : q = 5\n". All from one easily
written db(q) call.

The do and while(false) keywords force the statement containing db(q) to
finish with a healthy ; semicolon. Macros need techniques, like extra
parentheses, to avoid clashing with raw C++ statements.

On the ends of broken lines, two reverse solidi, \, join everything into one
long macro. The __FILE__ and __LINE__ symbols are magic constants, defined
by the C languages, which expand into the current name of the source file
and line number.

When a program encounters syntax errors, faults, or trace statements, the
same keystroke must navigate to any of them.

Visual Studio surfs to errors using <F8>: Go To Output Window Next Location.
The Windows SDK function to write text into the output panel, for this
feature to read it and surf to an error, is OutputDebugString().
Putting them all together yields this killer trace macro:

#define db(x_) do { std::stringstream z; \
z << __FILE__ << "(" << __LINE__ << ") : " \
#x_ " = " << x_ << endl; \
cout << z.str() << std::flush; \
OutputDebugStringA(z.str().c_str()); \
} while (false)

That takes any argument, including expressions, which support operator<<. We
will return to these techniques while exploring more Fault Navigation issues
in C++.

db(q) pushes "C:\path\source.cpp(99) : q = 5\n" into the Output Debug panel.
<F8> parses the file name and line number and navigates your editor directly
to the line containing the db(q).

Those are major wins. Tracing with db() is very low cost for very high
feedback.

C++ has flaws. But those of you inclined to dismiss it entirely are invited
to write db(), with all these features, in your favorite language.
 
R

Rich Grise

Phlip said:
Have you written a "hello world" program yet? And always learn C++ from
more than two tutorials, at the same time. Try /Accelerated C++/ by Koenig
and Moo.

I've copied and pasted one, yes. :) But this is just the first tutorial
I've checked - I've essentially just started with C++, and figured I should
start with the basics. :)
Unfortunately, yes. They are templates. (But the comments could use //
instead of /* */.)

The following dissertation intends to help people read C++, not write new
code. You would do me a major favor if you read the following and told me
where (if anywhere) you get lost.
OK:

Bjarne Stroustrup invented C++ to provide the popular but low-level C
language with the keywords virtual, template and operator. Those enable
Object Oriented techniques with minimal runtime overhead. C is "portable
assembler", and C++ is "portable OO assembler".

C++ in a Nutshell
C++ is a statically typed language. It has no latent "Object" base class
to supply default behaviors to all objects. C++ supports Object Oriented
techniques, but not everything in C++ is an object.

All C++ entities have a declaration and a definition. C++ uses a compiling
and linking system that compiles many declarations and a few definitions
together into one "object code file". Then many of these link together to
form a complete program.

Only source statements compiled below a declaration can use its
identifiers. Developers can declare and define classes and functions

This is the first mention of "function. Does it mean the same as in C?
simultaneously (the preferred way), or they can move declarations to
separate files.

Would this be as simple as taking the #includes and stuff and putting
them in a header file?

Declarations and definitions aren't too much different from what they
mean in C, are they?
This Case Study will show tests followed by the code that
passes them, but that code, or its declarations, must in source appear
above their tests.

C++ supports very large Object Oriented applications when modules
typesafely compile remote modules' interface declarations, without the
burden of recompiling their implementation definitions.

OK, I know what each of these words means, but I'm going to have to mull
over this particular permutation for awhile. :)

But this dissertation is exactly what I'm looking for - I'm really going
to mull, and mark your post as unread, and read the rest after I grasp the
paragraph above. (or at least read more - no guarantees yet!)

Thanks very much!
Rich
 
R

Rich Grise

Phlip said:
Have you written a "hello world" program yet? And always learn C++ from
more than two tutorials, at the same time. Try /Accelerated C++/ by Koenig
and Moo.

Well, I'm kind off school for the night - I might post asking if anyone
wants to be a free tutor, since this tutorial has a quiz at the end of the
chapter. But that's for tomorrow. Right now, I want to crack a joke about
Peter Müller's English in para. 2.5.3:
-----------------------------------
2.5.3 Missing Type Safety

In our list example we have to use the special type ANY to allow the list
to carry any data we like. This implies, that the compiler cannot guarantee
for type safety. Consider the following example which the compiler cannot
check for correctness:
PROCEDURE foo() BEGIN
SomeDataType data1;
SomeOtherType data2;
list_handle_t myList;

myList <- list_create();
list_append(myList, data1);
list_append(myList, data2); /* Oops */
...
list_destroy(myList);
END

It is in your responsibility to ensure that your list is used consistently.
A possible solution is to additionally add information about the type to
each list element. However, this implies more overhead and does not prevent
you from knowing what you are doing.
---------------------------------------------------------
My response to that last sentence: Maybe not, but it doesn't guarantee that
you _do_ know what you're doing! I'm assuming German is Mr. Müller's first
language, which if so, then the whole thing is an excellent translation,
but on this one sentence, it sounds like he means "does not relieve you
from responsibility to know what you are doing." Maybe even "protect,"
although that's remote. ;-)

Cheers!
Rich
 
P

Phlip

Rich said:
Consider the following example which the compiler cannot
check for correctness:
PROCEDURE foo() BEGIN
SomeDataType data1;
SomeOtherType data2;
list_handle_t myList;

myList <- list_create();
list_append(myList, data1);
list_append(myList, data2); /* Oops */

What language is that?

Eeeeeeewww, it doesn't use = for assignment, the way God intended!
 
P

Phlip

Rich said:
This is the first mention of "function. Does it mean the same as in C?

C++ inherits C. Hence any C nomeclature must be preserved. "function" is
"function", but "member function" is new.
Would this be as simple as taking the #includes and stuff and putting
them in a header file?

You are trying to say "put the declarations into header files". The standard
practice in C++ is to define classes in header files. That's subtly wrong,
so I can't say it this early then retract it.
Declarations and definitions aren't too much different from what they
mean in C, are they?

Right. C++ adds the ability to declare or define classes and member
functions.
OK, I know what each of these words means, but I'm going to have to mull
over this particular permutation for awhile. :)

My dissertation riffs from small scale (this is a header) to large scale
(this is the fundamental principle of how C++ weds logical decoupling with
physical decoupling) to small scale (this is operator<<).

Sorry. It won't happen again. But please claw your way just as far as my
utterly trite definition of "template"...
 
R

Rich Grise

Phlip said:
C++ inherits C. Hence any C nomeclature must be preserved. "function" is
"function", but "member function" is new.


You are trying to say "put the declarations into header files". The
standard practice in C++ is to define classes in header files. That's
subtly wrong, so I can't say it this early then retract it.

By this do you mean that "the standard practice ... is ..." is subtly
wrong, the "define classes in header files" is subtly wrong, or that
it's subtly wrong to map "put the declarations" onto "define classes",
even though the header file is the place that either (or maybe both?
That's part II of this Q. :) ) sits in the source files?
Right. C++ adds the ability to declare or define classes and member
functions.

Ah. And I read a definition of "class" today that I can wrap my headbone
around.
My dissertation riffs from small scale (this is a header) to large scale
(this is the fundamental principle of how C++ weds logical decoupling with
physical decoupling) to small scale (this is operator<<).

Cool! I rather like it - like I say, when I hit a stopper, I'll stop, but
I have a background processor in my head (everybody does, just not
everybody knows how to use it), so the answer will pop up while I'm doing
something else.
Sorry. It won't happen again.

Oh, please, continue! I'm still going back in the thread to the first
instance of your response and continue from the C++ philosophy, above. ;-)

I get it today. I can parse it and it's like, Oh, of course!

Thanks again, and like I say, I can't pay a tutor much, other than
the bragging points - "I tutored that registered BOZO, Rich Grise, in C++!"
But please claw your way just as far as my
utterly trite definition of "template"...
I certainly will - I was going to anyway, see above and plus, I wanna see
what you consider to be "utterly trite." ;-)

I've also started on another web tutorial, and have already learned
something that the other one either glossed over, or hasn't got to yet.
Good advice, thanks!

Cheers!
Rich
 
P

Phlip

Rich said:
By this do you mean that "the standard practice ... is ..." is subtly
wrong, the "define classes in header files" is subtly wrong, or that
it's subtly wrong to map "put the declarations" onto "define classes",
even though the header file is the place that either (or maybe both?
That's part II of this Q. :) ) sits in the source files?

C++, more than softer languages, relies on a "sane subset" of best
practices. Don't do sick things with #include, such as put it into the body
of a function, without a very good reason, for example.

Everyone thinks the standard practice with C++ is to put classes into header
files. That is subtly wrong. The better rule (leading to a saner subset) is
"Give identifiers the most restricted scope possible." So try to put classes
in .cpp files as often as possible.
Ah. And I read a definition of "class" today that I can wrap my headbone
around.

Good. Here's a declaration (not a definition):

class Foo;

You can now point or refer to Foo, but not use one.
I certainly will - I was going to anyway, see above and plus, I wanna see
what you consider to be "utterly trite." ;-)

Please go back to my original post and review the whole thing. You seem to
think I will write more. I won't until you get stuck on something there.
 

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

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,056
Latest member
GlycogenSupporthealth

Latest Threads

Top