By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,143 Members | 1,919 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,143 IT Pros & Developers. It's quick & easy.

Pointers and polymorphism explained [preview, PDF, part of my attempted "Correct C++ Tutorial"]

P: n/a
So, I got the itch to write something more...

I apologize for not doing more on the attempted "Correct C++ Tutorial"
earlier, but there were reasons.

This is an UNFINISHED and RAW document, and at the end there is even pure
mindstorming text left in, but already I think it can be very useful.

<url: http://home.no.net/dubjai/win32cpptut/special/pointers/preview/pointers_01__alpha.doc.pdf>.
What do you think?

In particular, if you find any grave errors, please do not hesitate to
comment. I always make errors. Those I agree are errors will be corrected.
Contents (so far):

1 1 Pointers.
1 1.1 Introduction to the basics.
1 1.1.1 How to obtain a pointer to a given object, and how to use that pointer.
3 1.1.2 The nullpointer value, valid and invalid pointers.
6 1.1.3 How to implement out-arguments by using pointers.
8 1.1.4 How to implement in-arguments by using pointers.
9 1.1.5 How to use C++ style references instead of C style pointers for arguments.
11 1.1.6 How to access main arguments.
12 1.1.7 Const-correctness for pointers (and references).
14 1.2 Run-time polymorphism.
14 1.2.1 Polymorphism.
16 1.2.2 The concept of linked data structures.
17 1.2.3 C-style polymorphism with simulated dynamic types (just one actual type).
19 1.2.4 Basic use of dynamic memory allocation & deallocation.
22 1.2.5 How to use function pointers to simulate dynamic types, C-style.
25 1.2.6 Using real types and inheritance for logical sub-types, mostly C-style.
32 1.2.7 Using vtables, mostly C-style (also a few words about abstract classes, etc.).
38 1.2.8 C++ virtual member functions.
45 1.2.9 C++ destructors and polymorphic delete.
49 1.2.10 Object ownership and the C++ std::auto_ptr.
53 1.2.11 C++ constructors and exception safety for new.
57 1.3 Dynamically allocated objects versus others.
58 1.3.1 Ensure dynamic allocation using C++ access specifiers and copy constructors.
61 – End Of Text –

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Oct 26 '05 #1
Share this Question
Share on Google+
53 Replies


P: n/a
Alf,

I don't think I can find errors for you, but read it I will.

Small note, the "green" color for highlighting on my screen is almost
no highlight whatsoever. Looks like the adjacent letters, unless I
really, really look at it.

Good subject, pointers.

- Robert -

Oct 26 '05 #2

P: n/a
Alf,

The program called bad_pointer02.cpp on page 4 [page 6 of pdf] returns
the proper value, 43. It did not seem to yield undefined behaviour.

I use MSVC line command running on XP.

I can't see where the program is wrong. The function is called, x is
created, the pointer is set to the location, and then return...oops. I
get it. But the program still returned the proper value. hmm... Bet
this happens everytime until you count on it.

- Robert -

Oct 26 '05 #3

P: n/a
Robert Macy wrote:
Alf,

The program called bad_pointer02.cpp on page 4 [page 6 of pdf] returns
the proper value, 43. It did not seem to yield undefined behaviour.


Actully, that is the tricky part of undefined behaviour. It often works
on one platform and fails on another.

Mirek
Oct 26 '05 #4

P: n/a
* Robert Macy:

Small note, the "green" color for highlighting on my screen is almost
no highlight whatsoever. Looks like the adjacent letters, unless I
really, really look at it.


Yes, that was intentionally. The idea is to make it clear, as one reads
the text, that this word or term is a new one, defined by the context.
Without drawing the eyes towards that word or term, and without making
it seem like a good idea to just skim those words or terms.

Originally they weren't even boldface.

But then I changed my mind: without boldface they appeared with _less_
contrast than the rest of the text...

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Oct 27 '05 #5

P: n/a
* Robert Macy:
Alf,

The program called bad_pointer02.cpp on page 4 [page 6 of pdf] returns
the proper value, 43. It did not seem to yield undefined behaviour.

I use MSVC line command running on XP.

I can't see where the program is wrong. The function is called, x is
created, the pointer is set to the location, and then return...oops. I
get it. But the program still returned the proper value. hmm... Bet
this happens everytime until you count on it.


Thanks for that comment, it's appreciated.

It just so happens that with the compiler options etc. you're using,
there's nothing that changes the contents of the chunk of memory that
the local variable occupied, between the time the pointer is obtained,
and the time the pointer is used -- Undefined Behavior is allowed to
do anything, including what someone might expect it to do, or not.

One simple way to trash that memory (overwrite it with something else),
is to call some function or, even just evaluating a suitable expression.

E.g., I think something like

std::cout << "Oops!" << std::endl;

after the call to wrongAnswer(), but before displaying the contents of
*p, would do the trick.

I'll probably put in a statement like the "Oops!", to make it even more
clear that this program is really really Undefined Behavior.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Oct 27 '05 #6

P: n/a

Alf P. Steinbach wrote:
So, I got the itch to write something more...

I apologize for not doing more on the attempted "Correct C++ Tutorial"
earlier, but there were reasons.

This is an UNFINISHED and RAW document, and at the end there is even pure
mindstorming text left in, but already I think it can be very useful.

<url: http://home.no.net/dubjai/win32cpptut/special/pointers/preview/pointers_01__alpha.doc.pdf>.
What do you think?

In particular, if you find any grave errors, please do not hesitate to
comment. I always make errors. Those I agree are errors will be corrected.


Hi Alf,

I am very busy at the moment, but I had a very, very brief look,
and a few things caught my eye, and that was to do with wording.

I will look at the rest when I get a chance.
Btw, it's just an opinion, so don't get too heated over it :-)

1 Pointers:
A pointer is a value that identifies where some object or
function is located in the computer's memory.

// I would have said something along the lines of:
* A pointer is a special type of variable that stores an address.

* The address stored in the pointer is an integral value, which
points to a location in the computer's memory.

* Just like an address that identifies where a house is located
on your street, the pointer address in turn identifies exactly
where in memory an object of a given type can be located.
1.1 Introduction to the basics.

// Remove this line or re-phrase it (covered in the text above):
A pointer that tells where an object o is located is said to point to
o.

// A few lines down we find:
*p = 42; Assigning to the object a pointer points to.
which doesn't change p, but the object that p points to.

That's called dereferencing. (*)

I think this (*) is a little misleading - Although the operation
is called assignment, it is not clear what you are actually calling
dereferencing. Even though you mention the dereferencing operator
a few more lines down, it has not been made clear what the act of
dereferencing actually means.

AFAIU, dereferencing is the act of applying an operator to a pointer
variable, to ultimately access the undelying value of the object being
pointed to - I think this or similar explanation should be provided
for the newbie.

// <nit> In the following sentence you have:
And to make p point to o you just apply the address operator, &, to o:

In this particular context, I always new this operator to be called
the "address of" operator, rather than just the "address operator".

// For your question in the following, I would add (shown below):
p = &o; // Set p to point to o.
*p = 42; // Assign
And, for example, does the order of the two commented statements
matter?

* Yes, it does matter, and that is where one advantage of
initialisation can help, if appropriate:

int* p( &o ); // no order to worry about

Sorry I could not look at more of your tutorial (for now), but I
will when I get some more time.

Hope my opinions were useful :-)

Cheers,
Chris Val

Oct 27 '05 #7

P: n/a
I got all the way through the first section!

I especially like your comment about reading the code from right to
left. I've been doing that technique with much of the help from the MS
website, not on a line basis, but on a conceptual basis. Right to
left? then it dawned on me that math is right to left. As in, C equals
A plus B etc. As opposed to A plus B equals C. Then I remembered, that
our math [numbers] came from Arabic origins which is also right to
left. All making more sense now.

However, I am stuck at one concept. On page 13 [page 15 of pdf] there
is a section of code that varies from ok to "not ok" at the last line.
I tried compiling the code into a simple program, test.cpp. On MSVC
line command on the XP, the compiler first would not accept a constant
*unless* the constant is initialized to some value. Nice check. And
sure enough, as you predicted, the compiler would not process the line
16

/* from page 15
*/
#include <iostream> // std::cout
#include <ostream> // std::endl

int main()
{
int o;
int const oConst = 1; // must initialize a constant
int* p = &o;
int const* pConst = &oConst;

pConst = p; // ok
pConst = pConst; // ok
p = p; // ok
p = pConst; // won't compile ??
}
/*
Line 16 prevents this from compiling
test.cpp(16) : error C2440: '=' : cannot convert from 'const int *' to
'int *'
Conversion loses qualifiers
*/

For me, it looked like pConst=p; should cause a problem. I must be
missing what the equals sign means here.

- Robert -

Oct 27 '05 #8

P: n/a
Robert Macy <ma**@california.com> wrote:
However, I am stuck at one concept. On page 13 [page 15 of pdf] there
is a section of code that varies from ok to "not ok" at the last line.
I tried compiling the code into a simple program, test.cpp. On MSVC
line command on the XP, the compiler first would not accept a constant
*unless* the constant is initialized to some value. Nice check. And
sure enough, as you predicted, the compiler would not process the line
16

int o;
int const oConst = 1; // must initialize a constant
int* p = &o;
int const* pConst = &oConst; [snip] p = pConst; // won't compile ?? test.cpp(16) : error C2440: '=' : cannot convert from 'const int *' to
'int *'
Conversion loses qualifiers For me, it looked like pConst=p; should cause a problem. I must be
missing what the equals sign means here.


When you try to assign "regular pointer = pointer to const", then that
implies that pointer should be allowed to change the object pointed to.
Trying to change a const object is very bad, so it was decided to
prevent that at compile time.
--
Marcus Kwok
Oct 27 '05 #9

P: n/a

Robert Macy wrote in message

However, I am stuck at one concept. On page 13 [page 15 of pdf] there
is a section of code that varies from ok to "not ok" at the last line.
I tried compiling the code into a simple program, test.cpp. On MSVC
line command on the XP, the compiler first would not accept a constant
*unless* the constant is initialized to some value. Nice check. And
sure enough, as you predicted, the compiler would not process the line
16

/* from page 15
*/
#include <iostream> // std::cout
#include <ostream> // std::endl

int main()
{
int o;
int const oConst = 1; // must initialize a constant
int* p = &o;
int const* pConst = &oConst;

pConst = p; // ok
pConst = pConst; // ok
p = p; // ok
p = pConst; // won't compile ??
}
/*
Line 16 prevents this from compiling
test.cpp(16) : error C2440: '=' : cannot convert from 'const int *' to
'int *'
Conversion loses qualifiers
*/

For me, it looked like pConst=p; should cause a problem. I must be
missing what the equals sign means here.

- Robert -


// p is pointing to memory that can be *read* or written to (RW).
*p = 43; // should be no problem.

pConst = p; // should not cause a problem. The 'int' *can* be read.
// *pConst = 43; // should cause a problem. "assignment of read-only
location"
// The 'int' is constant (RO), not the pointer to it.

int * const pcConst = &o;
// pcConst = p; // should cause a problem. The pointer is const.
// "assignment of read-only variable `pcConst' "
*pcConst = 43; // should not cause a problem. What it points to is RW.

int const * const pccConst = &oConst;
// pccConst = p; // nope. The pointer is const.
// *pccConst = 43; // nope. What it points to is RO.

--
Bob R
POVrookie
Oct 27 '05 #10

P: n/a
* Chris ( Val ):
* Alf P. Steinbach:

<url: http://home.no.net/dubjai/win32cpptut/special/pointers/preview/pointers_01__alpha.doc.pdf>.

What do you think?
I am very busy at the moment, but I had a very, very brief look,
and a few things caught my eye, and that was to do with wording.

I will look at the rest when I get a chance.
Btw, it's just an opinion, so don't get too heated over it :-)

1 Pointers:
A pointer is a value that identifies where some object or
function is located in the computer's memory.

// I would have said something along the lines of:
* A pointer is a special type of variable that stores an address.

* The address stored in the pointer is an integral value, which
points to a location in the computer's memory.

* Just like an address that identifies where a house is located
on your street, the pointer address in turn identifies exactly
where in memory an object of a given type can be located.


Well, I basically like your idea of pointing out (!) that a pointer is
effectively integral: you can increment and decrement pointers, and
there are no pointer values in between the values so generated (although
for some pointers these operations give undefined behavior).

There are however two reasons why I think it would not be a good idea to
mention that. First and foremost, the standard reserves the term
"integral type" to mean bool, char, wchar_t, and the signed and unsigned
integer types (the term integral type is defined in paragraph 3.9.1/7),
i.e.,

a pointer type is _not_ integral

in the standard's definition of the term. Second reason, I'd rather not
get into a discussion of raw arrays at this point, both because there's
so much said about that topic, and because the beginner is much better
served by using e.g. std::vector and std::string instead.

Regarding "special" and "variable": nope, a pointer is neither special
nor necessarily a variable. We often say that e.g. a function returns a
pointer to such and such. The function does not return a variable.

Regarding "an object": nope, a pointer does not necessarily point to an
object. ;-)

Actually I took pains to explain that last in detail, most of the ways
that a valid C++ pointer need _not_ point to an object. But then I
goofed on the introductory sentence! So thanks also for focusing on
that sentence. But how should it be rephrased? Perhaps put in the word
"basically" or some such, in parenthesis?

1.1 Introduction to the basics.

// Remove this line or re-phrase it (covered in the text above):
A pointer that tells where an object o is located is said to point to
o.
It defines the term "point to" (shown in bold green), not yet covered.

// A few lines down we find:
*p = 42; Assigning to the object a pointer points to.
which doesn't change p, but the object that p points to.

That's called dereferencing. (*)

I think this (*) is a little misleading - Although the operation
is called assignment, it is not clear what you are actually calling
dereferencing. Even though you mention the dereferencing operator
a few more lines down, it has not been made clear what the act of
dereferencing actually means.
Thanks -- perhaps just replace "that" by "applying *"?

AFAIU, dereferencing is the act of applying an operator to a pointer
variable, to ultimately access the undelying value of the object being
pointed to - I think this or similar explanation should be provided
for the newbie.

// <nit> In the following sentence you have:
And to make p point to o you just apply the address operator, &, to o:

In this particular context, I always new this operator to be called
the "address of" operator, rather than just the "address operator".
Not sure.

// For your question in the following, I would add (shown below):
p = &o; // Set p to point to o.
*p = 42; // Assign
And, for example, does the order of the two commented statements
matter?

* Yes, it does matter, and that is where one advantage of
initialisation can help, if appropriate:

int* p( &o ); // no order to worry about
Here I think I'll leave it as-is. In order to present a clean example I
deliberately did not use initialization. The example as-is shows that a
pointer variable isn't necessarily initialized at the point of
declaration. Bringing in C++ direct initializer syntax would just
confuse things, I think. Better with a minimal, clean example.

I hold to that guideline throughout the tutorial and this document.

For example, from a "best possible C++" view most of the classes I
present would benefit greatly from using constructors, access specifiers
and so on. But that would not help get across the points I want to get
across, it would just add more extranous things to deal with for the
reader (who possibly hasn't yet been introduced to those features, and
anyway does not necessarily see what their usage is all about in any
particular example). Instead I've chosen to present the minimum number
of concepts at a time, with minimum extranous clutter.

Sorry I could not look at more of your tutorial (for now), but I
will when I get some more time.

Hope my opinions were useful :-)


Yes, they were. Thank you,

- Alf

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Oct 27 '05 #11

P: n/a
* Robert Macy:

However, I am stuck at one concept. On page 13 [page 15 of pdf] there
is a section of code that varies from ok to "not ok" at the last line.
I tried compiling the code into a simple program, test.cpp. On MSVC
line command on the XP, the compiler first would not accept a constant
*unless* the constant is initialized to some value. Nice check.
Thanks, will fix.

...
For me, it looked like pConst=p; should cause a problem. I must be
missing what the equals sign means here.


The equals sign is just an ordinary assignment.

The assignment is accepted because you can't do any "harm" via the
pConst pointer.

But you're right that there _is_ a problem, namely that with the pConst
pointer in hand one might be expecting that it points to an unchanging
object. Then someone uses the p pointer that it came from, to change
that object, and whoops. The problem here is not the changing object,
but the expectation of an unchanging object.

A pointer to const does _not_ guarantee an unchanging object.

What it guarantees (except for using low-level features to circumvent
the rules) is that the object can't be changed via _that_ pointer, that
some code that only has _that_ pointer in hand, can't change the pointed
to object.

This should perhaps be discussed in greater detail.

I just said, look at it, then look at it again, until it's "obvious"...
;-)

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Oct 27 '05 #12

P: n/a
Alf P. Steinbach wrote:
Regarding "special" and "variable": nope, a pointer is neither special
nor necessarily a variable. We often say that e.g. a function
returns a pointer to such and such. The function does not return a
variable.


Actually, a function like the one you describe here doesn't return a
pointer. It returns a pointer *value*, which in this case is a constant
with a very short life expectancy (i.e. if you don't use it right away, it's
gone).
--

Sigurd
http://utvikling.com
Oct 27 '05 #13

P: n/a
Chris ( Val ) wrote:
* The address stored in the pointer is an integral value, which
points to a location in the computer's memory.


You imply a linear address space, and that is not necessarily correct.

Also, arithmetics are different for pointers than for integral types. For
instance, if you add 1 to a pointer the internal representation may increase
by any amount (depending on the size of what's pointed to).
--

Sigurd
http://utvikling.com
Oct 27 '05 #14

P: n/a
* Sigurd Stenersen:
Alf P. Steinbach wrote:
Regarding "special" and "variable": nope, a pointer is neither special
nor necessarily a variable. We often say that e.g. a function
returns a pointer to such and such. The function does not return a
variable.


Actually, a function like the one you describe here doesn't return a
pointer. It returns a pointer *value*, which in this case is a constant
with a very short life expectancy (i.e. if you don't use it right away, it's
gone).


Actually, it returns a pointer.

Depending on the context, the word "pointer" can mean

* A pointer value.

* A pointer variable.

* A pointer type.

The last usage is not very common in ordinary programming, but abounds
in the standard.

And the list above is not exhaustive. For example, we differentiate
between "raw pointers" and "smart pointers". Where "pointer" denotes a
more general _concept_, and is restricted to a specialization of that
concept by prepending a qualification.

So, it would be wrong, terminologically, to define pointer as
"variable".

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Oct 27 '05 #15

P: n/a
Alf P. Steinbach wrote:
* Sigurd Stenersen:
Alf P. Steinbach wrote:
Regarding "special" and "variable": nope, a pointer is neither
special nor necessarily a variable. We often say that e.g. a
function returns a pointer to such and such. The function does not
return a variable.
Actually, a function like the one you describe here doesn't return a
pointer. It returns a pointer *value*, which in this case is a
constant with a very short life expectancy (i.e. if you don't use it
right away, it's gone).


Actually, it returns a pointer.


Actually, that's sloppy language. The fact that a lot of people use sloppy
language does *not* mean it's correct.

Depending on the context, the word "pointer" can mean

* A pointer value.


In the given context, that is exactly what it means.
--

Sigurd
http://utvikling.com
Oct 27 '05 #16

P: n/a
Sigurd Stenersen wrote:
Alf P. Steinbach wrote:
* Sigurd Stenersen:
Alf P. Steinbach wrote:
Regarding "special" and "variable": nope, a pointer is neither
special nor necessarily a variable. We often say that e.g. a
function returns a pointer to such and such. The function does not
return a variable.

Actually, a function like the one you describe here doesn't return a
pointer. It returns a pointer *value*, which in this case is a
constant with a very short life expectancy (i.e. if you don't use it
right away, it's gone).


Actually, it returns a pointer.


Actually, that's sloppy language. The fact that a lot of people use
sloppy language does *not* mean it's correct.

Depending on the context, the word "pointer" can mean

* A pointer value.


In the given context, that is exactly what it means.


It is not sloppy language. The use by many people is, indeed immaterial, but
the use within the standard is not. The standard clearly blesses this use
of the word "pointer". That is what makes it correct (in this context).
Best

Kai-Uwe Bux
Oct 27 '05 #17

P: n/a
* Sigurd Stenersen:
Alf P. Steinbach wrote:
* Sigurd Stenersen:
Alf P. Steinbach wrote:
Regarding "special" and "variable": nope, a pointer is neither
special nor necessarily a variable. We often say that e.g. a
function returns a pointer to such and such. The function does not
return a variable.

Actually, a function like the one you describe here doesn't return a
pointer. It returns a pointer *value*, which in this case is a
constant with a very short life expectancy (i.e. if you don't use it
right away, it's gone).


Actually, it returns a pointer.


Actually, that's sloppy language. The fact that a lot of people use sloppy
language does *not* mean it's correct.

Depending on the context, the word "pointer" can mean

* A pointer value.


In the given context, that is exactly what it means.


Well, then by your own definition it's neither incorrect nor sloppy
language. ;-)

As I see it, the pointer value meaning is the basic meaning of pointer,
from which other meanings derive.

As you see it, the basic meaning is a pointer variable (I think you mean
"object", because in the standard's definition a variable needs a name).

As the authors of the Wikipedia article on pointers see it, the basic
meaning is a data type, "a pointer is a programming language data type".

Can we agree at least that "pointer" does have a broader meaning than
just "pointer variable", that it's _not_ incorrect or sloppy language to
say that a function returns a pointer?

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Oct 27 '05 #18

P: n/a
I'm still staring at it ! ! ! :-)

But, BobR's comments are making me start to think in terms of RO memory
and assignments rather than constants and equals. That is thinning the
fog a bit.

- Robert -

Oct 27 '05 #19

P: n/a
* Robert Macy:
I'm still staring at it ! ! ! :-)

But, BobR's comments are making me start to think in terms of RO memory
and assignments rather than constants and equals. That is thinning the
fog a bit.


Evidently, _much_ more detailed discussion than I provided is required.

Something like BobR's comments, on the basic meaning of 'const'.

Consider this:

int* p;

p = 0; // OK.
*p = 0; // OK when p points to some actual variable.

p is not constant. Read backwards: p is a pointer to a read/write int.
p can be assigned to. *p, the int, can be assigned to.

Since *p can be assigned to, you're not allowed to initialize p to point
to a constant int, or to later point it towards a constant int, because
then you could assign to that constant variable via *p = somevalue.

Next:

int const* p;

p = 0; // OK.
*p = 0; // !Not permitted.

p is not constant. Read backwards: p is a pointer to a constant, a
read-only, int. p can be assigned to. *p, the int, can only be read.

Since *p can only be read, p can be pointed to any int variable, because
all int variables support reading their contents.

Third:

int* const p = &o;

p = 0; // !Not permitted.
*p = 0; // OK when p points to some actual variable.

p is constant. Read backwards: p is a constant, a read-only pointer to
a read/write int. p can not be assigned to. *p, the int, can be
assigned to.

Since *p can be assigned to, you're not allowed to initialize p to point
to a constant int, because then you could assign to that variable via *p
= somevalue.

Finally:

int const* const p = &o;

p = 0; // !Not permitted.
*p = 0; // !Not permitted.

p is constant. Read backwards: p is a constant, a read-only pointer to
a constant, a read-only int. p can only be read. *p, the int, can only
be read.

Since *p can only be read, p can be pointed to any int variable, because
all int variables support reading their contents.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Oct 27 '05 #20

P: n/a
Alf P. Steinbach wrote:
E.g., I think something like

std::cout << "Oops!" << std::endl;

after the call to wrongAnswer(), but before displaying the contents of
*p, would do the trick.


Didn't mess up either. So I was going to try some other things, where
I needed another pointer, like...
int* p, q;
p = wrongAnswer(); // this line generates a compile error
q = p;
std::cout << *q << std::endl;

compiler says : error C2440: cannot convert from 'int' to 'int *'
Conversion from integral type to pointer type requires
reinterpret_cast, C-style cast or function-style cast

didn't like this line either
*p = wrongAnswer();

as expected, this works...
int* q;
int* p = wrongAnswer();
but the first failure makes no sense to me.

ARRRRGGGG!!!!!

instead of
int* p, q; //which looks like it should work to me

must do it this way...
int* p;
int* q;

THEN THE PROGRAM COMPILES. But with a warning !

Always gave a warning, just didn't notice until now.
warning C4172: returning address of local variable or temporary

Why is it not possible to use one line to declare pointers?
int* p, q; // just not allowed?

- Robert -

Oct 27 '05 #21

P: n/a
That's good.

Whew, now I can move on. :-)

- Robert -

Oct 27 '05 #22

P: n/a
* Robert Macy:
Alf P. Steinbach wrote:
E.g., I think something like

std::cout << "Oops!" << std::endl;

after the call to wrongAnswer(), but before displaying the contents of
*p, would do the trick.
Didn't mess up either.


It did when I tried it.
[snip] Why is it not possible to use one line to declare pointers?
int* p, q; // just not allowed?


There is an example & discussion at the start of section 1.1.1 (top of
page 2).

You can use a typedef of the pointer type.

But generally it's not a good idea to do that for the purpose of
declaring more than one pointer at once: instead, declare each pointer
in its own declaration.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Oct 27 '05 #23

P: n/a
Alf P. Steinbach wrote:
Can we agree at least that "pointer" does have a broader meaning than
just "pointer variable", that it's _not_ incorrect or sloppy language
to say that a function returns a pointer?


Yes, I agree. The reason that this is correct is that functions can return
nothing but values, so it's given that a returned pointer is in fact a
pointer value.

BTW I was not the one claiming that "pointer" means "variable".
--

Sigurd
http://utvikling.com
Oct 27 '05 #24

P: n/a
Robert Macy wrote:
Why is it not possible to use one line to declare pointers?
int* p, q; // just not allowed?


It IS possible. You just need to realize that the * belongs to the
variable, not the type. Hence,
int *p, *q;

Which (mostly) is a good thing, as it allows you to declare type variables
and type pointer variables in the same statement. E.g.
int i, j, *p, *q;
declares two ints and two int pointers.
--

Sigurd
http://utvikling.com
Oct 27 '05 #25

P: n/a

Robert Macy wrote in message
<11**********************@g49g2000cwa.googlegroups .com>...
Alf P. Steinbach wrote:
E.g., I think something like

std::cout << "Oops!" << std::endl;

after the call to wrongAnswer(), but before displaying the contents of
*p, would do the trick.
Didn't mess up either. So I was going to try some other things, where
I needed another pointer, like...
int* p, q;
p = wrongAnswer(); // this line generates a compile error
q = p;


[ Let's temporarily assume 'wrongAnswer()' did return a valid
pointer-to-int.]
Ouch!! You got bit by the ol' declaration-on-the-same-line trick.

q = *p; // q is an 'int', NOT a pointer.

That's why I like to 'stick the star onto the var'.
int *p, *q;
And you'll often see experts scream, "one declaration per line.".
int *p;
int *q;
Why is it not possible to use one line to declare pointers?
int* p, q; // just not allowed?

- Robert -


It is, BUT, the pointer does not bind to the 'int', but to the var ('p' in
this example). Mr. Eckel, in TiCpp v1 Chap 3, states it like:
(you can say that “* binds more tightly to the identifier”).

That help? (I'm trying *not* to step on Mr. Steinbach's star(pun intended) ,
it's his show. (...and I consider him the 'mentor' and me 'D dummy' <G>) ).
--
Bob R
POVrookie
Oct 27 '05 #26

P: n/a
On Thu, 27 Oct 2005 21:30:01 +0200, "Sigurd Stenersen"
<si*****@utvikling.com> wrote:
int *p, *q;

Which (mostly) is a good thing, as it allows you to declare type variables
and type pointer variables in the same statement. E.g.
int i, j, *p, *q;
declares two ints and two int pointers.


You are correct that it is allowed. But it can lead to errors either
for the unwary or the overworked and tired. Note that Robert Macy,
who started this thread, made this type of error. I believe that it
is a style issue. I would recommend, in general, having one
declaration per line.
--

Best wishes,

Bob
Oct 28 '05 #27

P: n/a
I have actually adopted this technique throughout, including simple
declarations.

It allows me to "lump" the variables into sections that are easy for me
to review, change, etc.

Alas, the sequential/nonrealtime aspects prevent me from trusting using
all the module-ifications possible in C++ so I'm stuck with some *very*
lengthy inline coding. I wonder who started the thinking that a
computer has all day to go do each/all task(s) you ask of it. Probably
the same people that think a 100MB program is small.

- Robert -

Oct 28 '05 #28

P: n/a
* Alf P. Steinbach:

<url: http://home.no.net/dubjai/win32cpptut/special/pointers/preview/pointers_01__alpha.doc.pdf>.
Thanks to all who commented on the 1st version: Robert Macy, Chris Val,
BobR, and Sigurd Stenersen (I hope I haven't forgotten anybody!).

Most of this is now fixed, I think:

* Definition of "pointer" (more details added).
* Definition of "dereference" (better focused).
* Better more detailed discussion of const and const correctness.
* The bad pointer 2 UB program "improved" to be more overtly UB.
* The vtable figure improved (alas OpenOffice makes figures look bad).
* Renamed a member function for C++-oriented versions of the example
program in section 1.2, added discussion.
* Completed section 1.3.1 about ensuring dynamic allocation.

And regarding 1.3.1 I think I like this method better than the one in
the FAQ, even though this method is theoretically a more limited one
than the FAQ's completely general method (one line per class is much
better than a number of factory functions per class, I think!).

Updated version at:
<url:
http://home.no.net/dubjai/win32cpptut/special/pointers/preview/pointers_01__alpha2.doc.pdf>.

Further comments are welcome! ;-)

Contents (so far) -- the page numbers are probably incorrect since
this was for the original version, but the sections are the same:
1 1 Pointers.
1 1.1 Introduction to the basics.
1 1.1.1 How to obtain a pointer to a given object, and how to use that pointer.
3 1.1.2 The nullpointer value, valid and invalid pointers.
6 1.1.3 How to implement out-arguments by using pointers.
8 1.1.4 How to implement in-arguments by using pointers.
9 1.1.5 How to use C++ style references instead of C style pointers for arguments.
11 1.1.6 How to access main arguments.
12 1.1.7 Const-correctness for pointers (and references).
14 1.2 Run-time polymorphism.
14 1.2.1 Polymorphism.
16 1.2.2 The concept of linked data structures.
17 1.2.3 C-style polymorphism with simulated dynamic types (just one actual type).
19 1.2.4 Basic use of dynamic memory allocation & deallocation.
22 1.2.5 How to use function pointers to simulate dynamic types, C-style.
25 1.2.6 Using real types and inheritance for logical sub-types, mostly C-style.
32 1.2.7 Using vtables, mostly C-style (also a few words about abstract classes, etc.).
38 1.2.8 C++ virtual member functions.
45 1.2.9 C++ destructors and polymorphic delete.
49 1.2.10 Object ownership and the C++ std::auto_ptr.
53 1.2.11 C++ constructors and exception safety for new.
57 1.3 Dynamically allocated objects versus others.
58 1.3.1 Ensure dynamic allocation using C++ access specifiers and friendship.
61 – End Of Text –


--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Oct 28 '05 #29

P: n/a
Alf P. Steinbach wrote:
So, I got the itch to write something more...

I apologize for not doing more on the attempted "Correct C++ Tutorial"
earlier, but there were reasons.

This is an UNFINISHED and RAW document, and at the end there is even pure
mindstorming text left in, but already I think it can be very useful.

<url: http://home.no.net/dubjai/win32cpptut/special/pointers/preview/pointers_01__alpha.doc.pdf>.
What do you think?

In particular, if you find any grave errors, please do not hesitate to
comment. I always make errors. Those I agree are errors will be corrected.


It looks good, I'm pleased to say.

I'd take issue with
"Oddly enough C++ allows you to implement a pure virtual member
function in the same class it’s declared as pure virtual in, and
the effect is then only to make the class abstract."
as the effect of marking a member function as pure virtual is to
make abstract both the class in which it is so marked and any
descendent class until that member function is overridden by one
that is *not* pure.

To illustrate: attempting to compile the code

struct a {
virtual void f() = 0;
};
void a::f() {}

struct b:a {
};

int main() {
b the_b;
}

will generate an error message at the attempted declaration of
the_b in main, as b is an abstract class. Here's the output
from two compilers (of the two, como is of course the more
trustworthy when it comes to standards compliance):

bash-2.05a$ make alf
g++ -Wall -g alf.cpp -o alf
alf.cpp: In function `int main()':
alf.cpp:14: error: cannot declare variable `the_b' to be of type `b'
alf.cpp:14: error: because the following virtual functions are abstract:
alf.cpp:6: error: virtual void a::f()
make: *** [alf] Error 1
bash-2.05a$ como alf.cpp
Comeau C/C++ 4.3.3 (Feb 3 2005 16:38:26) for MAC_OS_X_Alpha1
Copyright 1988-2005 Comeau Computing. All rights reserved.
MODE:strict errors C++

"alf.cpp", line 14: error: object of abstract class type "b" is not allowed:
pure virtual function "a::f" has no overrider
b the_b;
^

1 error detected in the compilation of "alf.cpp".

I've only spotted one typo, which is in the footnote "In C++ one
can also omit the * in a declaration of a formal function argument
that is a function pointer, because C++ supports supports function
types, and an argument of function type is adjusted to function
pointer type", where the word "supports" is duplicated.

This work in progress shows much promise. With thought I might be
able to suggest improvements on the notes on static_cast for
downcasting (I'm not sure of the best way to raise the fact that
dynamic_cast is sometimes required), and I'll get around to reading
the end of this.

-- James
Oct 29 '05 #30

P: n/a
Sigurd Stenersen wrote:
Alf P. Steinbach wrote:
* Sigurd Stenersen:
Alf P. Steinbach wrote:

Regarding "special" and "variable": nope, a pointer is neither
special nor necessarily a variable. We often say that e.g. a
function returns a pointer to such and such. The function does not
return a variable.

Actually, a function like the one you describe here doesn't return a
pointer. It returns a pointer *value*, which in this case is a
constant with a very short life expectancy (i.e. if you don't use it
right away, it's gone).


Actually, it returns a pointer.

Actually, that's sloppy language. The fact that a lot of people use sloppy
language does *not* mean it's correct.


The fact that one group of people uses one particular formal
definition of a term does not mean that that definition is the
most correct, or that other definitions are incorrect.

It does mean that we're best to remember that definitions are
not universal, and be clear where necessary what we mean when
we use an overloaded term.

-- James
Oct 29 '05 #31

P: n/a
* James Dennett:
* Alf P. Steinbach:

So, I got the itch to write something more...

I apologize for not doing more on the attempted "Correct C++ Tutorial"
earlier, but there were reasons.

This is an UNFINISHED and RAW document, and at the end there is even pure
mindstorming text left in, but already I think it can be very useful.

<url: http://home.no.net/dubjai/win32cpptut/special/pointers/preview/pointers_01__alpha.doc.pdf>.
What do you think?

In particular, if you find any grave errors, please do not hesitate to
comment. I always make errors. Those I agree are errors will be corrected.
It looks good, I'm pleased to say.

I'd take issue with
"Oddly enough C++ allows you to implement a pure virtual member
function in the same class it’s declared as pure virtual in, and
the effect is then only to make the class abstract."
as the effect of marking a member function as pure virtual is to
make abstract both the class in which it is so marked and any
descendent class until that member function is overridden by one
that is *not* pure.


Thanks.

I thought that was already discussed earlier in section 1.2.7, but
checking the text I find that it was only implicit, "A class that has no
abstract methods, i.e. it implements all abstract methods from its base
class, if any, and doesn’t introduce any new ones itself, is
correspondingly called a concrete class." -- not explicitly stated!

Will fix. I'll probably use your words more or less unchanged! ;-)

I've only spotted one typo, which is in the footnote "In C++ one
can also omit the * in a declaration of a formal function argument
that is a function pointer, because C++ supports supports function
types, and an argument of function type is adjusted to function
pointer type", where the word "supports" is duplicated.
Thanks again, will fix.

This work in progress shows much promise. With thought I might be
able to suggest improvements on the notes on static_cast for
downcasting (I'm not sure of the best way to raise the fact that
dynamic_cast is sometimes required)
Well, this is (intended as) a kind of "problem - solution" driven
exposition, and nothing that requires RTTI (dynamic_cast or typeid) has
surfaced yet. Possibly RTTI deserves its own subsection, not to mention
section, or chapter. E.g., students who go on to write shoot-em-up
games often get stranded because they don't know how to design the
system so that the X and Y-dependent effect of "X shoots at Y" can be
naturally expressed without having to use large switch statements (if
you're such a student reading this, one (limited) solution is to use the
visitor pattern, which centralizes the few necessary dynamic_cast's).

and I'll get around to reading the end of this.


:-)

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Oct 29 '05 #32

P: n/a
* Alf P. Steinbach:

In particular, if you find any grave errors, please do not hesitate to
comment. I always make errors. Those I agree are errors will be corrected.


I found one. It's just a typo (thinking ahead and somehow shades of
those thoughts transferred to my fingers), but occurs in two places, so
it's serious. Namely, I've used the word "specialization" for a
template "instantiation" -- and those are very different things.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Oct 29 '05 #33

P: n/a
ARRRRGGGG!!!!!

Speaking from the standpoint of a complete newbie, translate that term
to idiot, I have no idea the point you're making in the polymorphism
section describing linked data structures. The first example program
starts on page 17 [page 19 of pdf] which is a program to find 2x+5.
The length of the program and the excesses gone to in the following
four programs to do this simple task, well, brings to mind a rude term.
I know you're trying to teach a principle here, but I think I missed
the principle.

Ok, the first program has weaknesses, but compiles, and runs. The
second program fixes some weakness, compiles, and runs. Each time the
new version of the program fixes a weakness in the previous program. I
very much like that, good learning structure, albeit I don't see the
weakness, but then again I didn't even understand the program.

However, we get to the third program starting on page 25 [page 27 of
pdf]. It is missing critical sections relating to identity and product
so it won't compile. Ok, ok. Something I should be able to do. After
studying the structures of the first two programs, it should be
possible to add the proper code to make expr_like_c_3.cpp compile. But
alas after 5 hours I still don't have the pieces. Maybe one piece I
could handle, but I'm not doing well on both, because I don't know what
the pieces are supposed to do. So it's time to whine.

Well, at least you didn't say, "It's obvious to the casual observer."
or "I leave it to the student to fill in these pieces." :-)

Give it a few more days and maybe it'll dawn on me what goes there.

- Robert -

PS: It would be a nice feature to have a copy of all your source code
zipped for download. The pdf to text converter I'm using likes to
munge the code by removing redundant characters. No end of havoc when
it does that to // comment lines, or randomly to function names like
Expression becoming Expresion.

Oct 29 '05 #34

P: n/a
* Robert Macy:
ARRRRGGGG!!!!!

Speaking from the standpoint of a complete newbie, translate that term
to idiot,
Uh oh. There's a big difference between not _knowing_ and being stupid.
I assume the reader is one how doesn't already know, but is rather
intelligent, like you. ;-)

I have no idea the point you're making in the polymorphism
section describing linked data structures. The first example program
starts on page 17 [page 19 of pdf] which is a program to find 2x+5.
Thanks, this is a good point. I tried to be clear that it's _not_ a
program to find (or evaluate) 2x+5, but clearly that point wasn't
expressed clearly enough... Here's a program to just evaluate 2x+5:

#include <iostream>
#include <ostream>

int main()
{
for( int x = 0; x <= 4; ++x )
{
std::cout << x << ": " << 2*x+5 << std::endl;
}
}

One could put 2*x+5 in a separate function (and _that_'s an exercise for
the student), but still that would just be a program to evaluate 2x+5.

A structured data representation of an expression, in contrast, can be

* displayed, in various ways

* stored in a file (this is called serialization),

* retrieved from a file (this is called de-serialization),

* symbolically integrated (yielding x^2 + 5x + C),

* symbolically differentiated (yielding 2),

* simplified (e.g. x+x+x can be simplified to 3*x)

* dynamically combined with other expressions,

and so on and on, all in addition to simple evaluation -- the point of
the code is its _potential_, not the concrete expression used, or even
what it actually does with that concrete expression, which is just to
evaluate it to show that the representation is good enough for that.

Now to add this clarification to the text...

The length of the program and the excesses gone to in the following
four programs to do this simple task, well, brings to mind a rude term.
I know you're trying to teach a principle here, but I think I missed
the principle.

Ok, the first program has weaknesses, but compiles, and runs. The
second program fixes some weakness, compiles, and runs. Each time the
new version of the program fixes a weakness in the previous program. I
very much like that, good learning structure, albeit I don't see the
weakness, but then again I didn't even understand the program.

However, we get to the third program starting on page 25 [page 27 of
pdf]. It is missing critical sections relating to identity and product
so it won't compile. Ok, ok. Something I should be able to do. After
studying the structures of the first two programs, it should be
possible to add the proper code to make expr_like_c_3.cpp compile. But
alas after 5 hours I still don't have the pieces. Maybe one piece I
could handle, but I'm not doing well on both, because I don't know what
the pieces are supposed to do. So it's time to whine.
For 'identity', copy the code for 'constant', rename things, and just
fix identity_valueOf so that it returns its x argument.

For 'product', copy the code for 'sum', rename things, and just replace
'+' with '*'... ;-)

Well, at least you didn't say, "It's obvious to the casual observer."
or "I leave it to the student to fill in these pieces." :-)

Give it a few more days and maybe it'll dawn on me what goes there.

- Robert -

PS: It would be a nice feature to have a copy of all your source code
zipped for download. The pdf to text converter I'm using likes to
munge the code by removing redundant characters. No end of havoc when
it does that to // comment lines, or randomly to function names like
Expression becoming Expresion.


Thanks, I think I'll do that.

Cheers,

- Alf

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Oct 29 '05 #35

P: n/a

Alf P. Steinbach wrote:
Uh oh. There's a big difference between not _knowing_ and being stupid.
I assume the reader is one how doesn't already know, but is rather
intelligent, like you. ;-)
I can listen to this all day.
For 'identity', copy the code for 'constant', rename things, and just
fix identity_valueOf so that it returns its x argument.

For 'product', copy the code for 'sum', rename things, and just replace
'+' with '*'... ;-)


As a double check. Is this "correct"?

/* from page 27 - 29
*/
#include <iostream> // std::cout
#include <ostream> // <<, std::endl

//------------------------------ General expression:

struct Expression; // Explains that Expression is a struct...
typedef Expression const* ExpressionPtr; // ... so that this is
accepted..
typedef double (*ValueOfFunc)( ExpressionPtr e, double x ); // ... and
this.

struct Expression
{
ValueOfFunc valueOf;
double value; // For constant.
ExpressionPtr pLeft; // For sum and product.
ExpressionPtr pRight; // For sum and product.
};

ExpressionPtr newExpression(
ValueOfFunc aValueOfFunc,
double aNumber,
ExpressionPtr aLeftPointer,
ExpressionPtr aRightPointer
)
{
Expression* pResult = new Expression;

pResult->valueOf = aValueOfFunc;
pResult->value = aNumber;
pResult->pLeft = aLeftPointer;
pResult->pRight = aRightPointer;
return pResult;
}

void destroy( ExpressionPtr e )
{
if( e != 0 )
{
destroy( e->pLeft );
destroy( e->pRight );
}
delete e;
}

double constant_valueOf( ExpressionPtr self, double /*x*/ )
{ return self->value; }

ExpressionPtr constant( double value )
{ return newExpression( &constant_valueOf, value, 0, 0 ); }
double identity_valueOf( ExpressionPtr self, double x )
{ return x; }

ExpressionPtr identity()
{ return newExpression( &identity_valueOf, 0, 0, 0 ); }
double product_valueOf( ExpressionPtr self, double x)
{
ExpressionPtr const left = self->pLeft;
ExpressionPtr const right = self->pRight;
return left->valueOf( left, x ) * right->valueOf( right, x );
}

ExpressionPtr product( ExpressionPtr left, ExpressionPtr right )
{ return newExpression( &product_valueOf, 0, left, right ); }
double sum_valueOf( ExpressionPtr self, double x )
{
ExpressionPtr const left = self->pLeft;
ExpressionPtr const right = self->pRight;
return left->valueOf( left, x ) + right->valueOf( right, x );
}

ExpressionPtr sum( ExpressionPtr left, ExpressionPtr right )
{ return newExpression( &sum_valueOf, 0, left, right ); }
int main()
{
// 2x + 5
ExpressionPtr const e = sum( product( constant( 2 ), identity() ),
constant( 5 ) );

for( int x = 0; x <= 4; ++x )
{
std::cout << x << " " << e->valueOf( e, x ) << std::endl;
}
destroy( e );
}
/* SCREEN PRINTOUT
0 5
1 7
2 9
3 11
4 13

*/

It compiles and creates the correct answers, but that doesn't mean the
pieces are correct. Could just be a "stumble" answer.

- Robert -

Oct 30 '05 #36

P: n/a
* Robert Macy:

Alf P. Steinbach wrote:
For 'identity', copy the code for 'constant', rename things, and just
fix identity_valueOf so that it returns its x argument.

For 'product', copy the code for 'sum', rename things, and just replace
'+' with '*'... ;-)


As a double check. Is this "correct"?


Looks OK.

Now I wonder, is the _first_ of these programs now clear?

I'd guess, if it isn't, that it's the recursive valueOf that is the
first thing there that is difficult to understand?

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Oct 30 '05 #37

P: n/a
* Alf P. Steinbach:
* James Dennett:

I'd take issue with
"Oddly enough C++ allows you to implement a pure virtual member
function in the same class it’s declared as pure virtual in, and
the effect is then only to make the class abstract."
as the effect of marking a member function as pure virtual is to
make abstract both the class in which it is so marked and any
descendent class until that member function is overridden by one
that is *not* pure.


Thanks.

I thought that was already discussed earlier in section 1.2.7, but
checking the text I find that it was only implicit, "A class that has no
abstract methods, i.e. it implements all abstract methods from its base
class, if any, and doesn’t introduce any new ones itself, is
correspondingly called a concrete class." -- not explicitly stated!

Will fix. I'll probably use your words more or less unchanged! ;-)


On second thoughts, is the following replacement text OK, do you think?

(I've cautioned several places that an implementation doesn't
necessarily use a vtable, so that's not repeated here.)

"Oddly enough C++ allows you to implement a pure virtual member function
in the same class it's declared as pure virtual in. This implementation
must then be provided textually outside the class definition, and the
only way to call it is to use a non-virtual call (a call that doesn't
use the vtable). I haven't shown how to do either, but it's not really
something you need yet. Just note that giving a member function an
implementation in the same class it's declared as pure virtual in,
doesn't make it less abstract: conceptually its vtable entry is still 0,
because that implementation can't and will never be called via the
vtable. So the function and the class is still abstract."

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Oct 30 '05 #38

P: n/a
Alf P. Steinbach wrote:
* Alf P. Steinbach:
* James Dennett:
I'd take issue with
"Oddly enough C++ allows you to implement a pure virtual member
function in the same class it’s declared as pure virtual in, and
the effect is then only to make the class abstract."
as the effect of marking a member function as pure virtual is to
make abstract both the class in which it is so marked and any
descendent class until that member function is overridden by one
that is *not* pure.


Thanks.

I thought that was already discussed earlier in section 1.2.7, but
checking the text I find that it was only implicit, "A class that has no
abstract methods, i.e. it implements all abstract methods from its base
class, if any, and doesn’t introduce any new ones itself, is
correspondingly called a concrete class." -- not explicitly stated!

Will fix. I'll probably use your words more or less unchanged! ;-)

On second thoughts, is the following replacement text OK, do you think?

(I've cautioned several places that an implementation doesn't
necessarily use a vtable, so that's not repeated here.)

"Oddly enough C++ allows you to implement a pure virtual member function
in the same class it's declared as pure virtual in. This implementation
must then be provided textually outside the class definition, and the
only way to call it is to use a non-virtual call (a call that doesn't
use the vtable). I haven't shown how to do either, but it's not really
something you need yet. Just note that giving a member function an
implementation in the same class it's declared as pure virtual in,
doesn't make it less abstract: conceptually its vtable entry is still 0,
because that implementation can't and will never be called via the
vtable. So the function and the class is still abstract."


Assuming that the vtable notion is clear enough to people, that
looks good enough to me. (I'd be tempted to expand that vtable
entries are usually set to something like pure_virtual_called
instead of literally to null pointers, but then I have a tendency
to dump too much information on people at once, and this may well
be something that doesn't add clarity for your target audience.)
So long as it's clear to readers that marking a member function
as pure means "must be overridden by any concrete derived class,
but does not have to be implemented in this abstract class",
then I think the fact that pure virtuals can be implemented is
less confusing than in the more conventional presentation of pure
as meaning "has no implementation in this class".

-- James
Oct 30 '05 #39

P: n/a
* Alf P. Steinbach -> Robert Macy:

Now I wonder, is the _first_ of these programs now clear?

I'd guess, if it isn't, that it's the recursive valueOf that is the
first thing there that is difficult to understand?


I have now added some explanation of how valueOf works.

Plus, the example programs now display the expression. Which is a bit
more code, but gives a better idea of the general structure. I think.

Plus, added explanation of what the examples are all about (that the
goal is not to display values of some concrete expression).

<url:
http://home.no.net/dubjai/win32cpptut/special/pointers/preview/pointers_01__alpha3.doc.pdf>.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Oct 31 '05 #40

P: n/a

Alf P. Steinbach wrote:
<url:
http://home.no.net/dubjai/win32cpptut/special/pointers/preview/pointers_01__alpha3.doc.pdf>.


Alf -

I posted a response a few days ago (probably soon after your original
posting), but it has not shown up yet. Quite possible that I sent it
to your email rather than the newsgroup.

In any case, I remember making the following comments:

* It would be good to have some "front matter" - initial content that
says who the intended audience is, what they are expected to know, and
what they should (and should not) expect to learn from this document.

* A tutorial on pointers should not assume the reader to know what
"rvalue" means.

* I initially made a comment requesting broader coverage on const
correctness. Looks like you have expanded it; will review.

best wishes,
- Anand Hariharan

Nov 1 '05 #41

P: n/a
* Anand Hariharan:

Alf P. Steinbach wrote:
<url:
http://home.no.net/dubjai/win32cpptut/special/pointers/preview/pointers_01__alpha3.doc.pdf>.

Alf -

I posted a response a few days ago (probably soon after your original
posting), but it has not shown up yet. Quite possible that I sent it
to your email rather than the newsgroup.

In any case, I remember making the following comments:

* It would be good to have some "front matter" - initial content that
says who the intended audience is,


If someone reads a text about pointers in C++, that rather narrows it
down, doesn't it?

In short, the audience is anyone who'd start reading.

Perhaps a short comment: "You're reading this, so you're in the intended
audience"?

But on second thoughts, perhaps better not...

what they are expected to know,
Basic C++. But I'm not a fan of listing requirements. That's just
shutting people out: those who don't think they have what's listed, and
those who have far more, and think "I've got nothing to learn here".
With the earlier installments of that tutorial it turned out that even
world-class experts had things to learn -- it's so easy to take the
basics for granted, but when it's examined one finds interesting things.
I also learned some things, of course, from the feedback and discussion.

and
what they should (and should not) expect to learn from this document.
That's the table of contents. :-)

* A tutorial on pointers should not assume the reader to know what
"rvalue" means.
I'm aware that I've used the word before defining it, somewhere.
Perhaps a footnote referring to the later definition?

* I initially made a comment requesting broader coverage on const
correctness. Looks like you have expanded it; will review.


--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Nov 1 '05 #42

P: n/a
In defense of leaving OUT the "who" should read this and the "what" you
should know...I read this because of the title -the subject line - I
need to understand pointers better and later I think I'll need to
understand polymorphism to take advantage of code already written. So
I waded in.

In defense of leaving OUT the "what" you should know...Does *anybody*
really know what they know? I mean the people that feel they know the
least about a subject usually are experts in it. Couple that lack of
self awareness with the hit and miss, spotty learning of programming
and it seems unlikely to find a uniform depth knowledge of programming
in a person, well at least a quantifiable measure of uniform depth of
knowledge of programming.

Besides listing requirements seems a bit pompous. Anybody who starts
reading will quickly learn they have the background, or they do not.
Also, they will learn whether the subject matter is taking them where
they want to go, or it is not. Any preface describing the path is
clutter which I have trouble reading/getting passed. I rarely read any
document containing such a preface, because I have just learned nothing
from reading that part, so why should I think more information will
follow? And I stop.

Yes, the table of contents was what I used/read to determine the path
Alf's project was going to take. In that table of contents was not just
a description of the path, but a quick thumbnail sketch of the
"organization" of the presentation to follow - a valuable roadmap to
keep in mind. Having read the table of contents I gained something.
Having read a preface that describes what I should know and will
shortly learn is of NO value.

Regarding definitions...For this newbie, two words meant little as far
as their implications were concerned. vtable and rvalue Here, a
"glossary" would have helped. Like an expanded footnote perhaps a page
(or more) long, but detailed enough to find out what the terms mean and
get some concept of what the implications of using them would be. A
separate section allows the newbie to learn, and the expert to gloss
over. Is that where the phrase glossary came from?

For me, this project went from learning basic concepts and principles
[useful background for all programming] and literally plowed me to a
dead stop into such advanced considerations my head is still spinning.
However, each day I go back to where I mired and push a little further.
Surprisingly, going on passed my point of understanding, and then
coming back to where I stopped understanding has helped. Which brings
me to my favorite question/subject. "Should we let children learn at
their own speed?" If this means don't hold them back, YES. If this
means, let them dawdle, NO. And that brings me back to Alf's work. He
certainly isn't letting me dawdle.

- Robert -

Nov 1 '05 #43

P: n/a
In article <ra********************@telenor.com>,
Sigurd Stenersen <si*****@utvikling.com> wrote:
Alf P. Steinbach wrote:
Regarding "special" and "variable": nope, a pointer is neither special
nor necessarily a variable. We often say that e.g. a function
returns a pointer to such and such. The function does not return a
variable.


Actually, a function like the one you describe here doesn't return a
pointer. It returns a pointer *value*, which in this case is a constant
with a very short life expectancy (i.e. if you don't use it right away, it's
gone).


Yep. Pointer is one of those words we like to toss about, generically,
but when you get into the language itself, it does end up needing to
be qualified.
--
Greg Comeau / Celebrating 20 years of Comeauity!
Comeau C/C++ ONLINE ==> http://www.comeaucomputing.com/tryitout
World Class Compilers: Breathtaking C++, Amazing C99, Fabulous C90.
Comeau C/C++ with Dinkumware's Libraries... Have you tried it?
Nov 5 '05 #44

P: n/a
In article <43****************@news.individual.net>,
Alf P. Steinbach <al***@start.no> wrote:
* Sigurd Stenersen:
Alf P. Steinbach wrote:
> Regarding "special" and "variable": nope, a pointer is neither special
> nor necessarily a variable. We often say that e.g. a function
> returns a pointer to such and such. The function does not return a
> variable.


Actually, a function like the one you describe here doesn't return a
pointer. It returns a pointer *value*, which in this case is a constant
with a very short life expectancy (i.e. if you don't use it right away, it's
gone).


Actually, it returns a pointer.

Depending on the context, the word "pointer" can mean

* A pointer value.

* A pointer variable.

* A pointer type.

The last usage is not very common in ordinary programming, but abounds
in the standard.

And the list above is not exhaustive. For example, we differentiate
between "raw pointers" and "smart pointers". Where "pointer" denotes a
more general _concept_, and is restricted to a specialization of that
concept by prepending a qualification.

So, it would be wrong, terminologically, to define pointer as
"variable".


Yes, it would be formally incorrect, if it were only defined as such.
--
Greg Comeau / Celebrating 20 years of Comeauity!
Comeau C/C++ ONLINE ==> http://www.comeaucomputing.com/tryitout
World Class Compilers: Breathtaking C++, Amazing C99, Fabulous C90.
Comeau C/C++ with Dinkumware's Libraries... Have you tried it?
Nov 5 '05 #45

P: n/a
In article <11**********************@g49g2000cwa.googlegroups .com>,
Robert Macy <ma**@california.com> wrote:
Why is it not possible to use one line to declare pointers?
int* p, q; // just not allowed?


It is possible, just not the way you think.
Just like say a typedef is not just text substitution,
the parsing of the above does not necessarily link the * and int,
therefore in short p is an int *, and q is an int. if you
want them both to be int * you would write:

int *p, *q;

due to how C++ and C treat declarators (which involve *'s
among other things). However, usually you want this:

int *p;
int *q;

and furthermore, the opportunity to intiialize them
whenever and whereever possible, and to document them.
--
Greg Comeau / Celebrating 20 years of Comeauity!
Comeau C/C++ ONLINE ==> http://www.comeaucomputing.com/tryitout
World Class Compilers: Breathtaking C++, Amazing C99, Fabulous C90.
Comeau C/C++ with Dinkumware's Libraries... Have you tried it?
Nov 5 '05 #46

P: n/a
Alf P. Steinbach <al***@start.no> wrote:
<url:
http://home.no.net/dubjai/win32cpptut/special/pointers/preview/pointers_01__alpha3.doc.pdf>.


Hi Alf, I made some notes for alpha3. However, most of them seem to
only be minor grammatical things that (IMHO) I think should be reworded.

p.1
--"We also say that a variable, or other object, that can hold a pointer
value, is a pointer."

--I would use parentheses instead, as I think there are too many
commas.

"We also say that a variable (or other object) that can hold ..."

--"some times"

--Thoughout, I would use "sometimes" instead of "some times"

--"and is essential to for example modern GUI (graphical user interface)
programming."

--I would add commas here

"and is essential to, for example, modern GUI ..."

--"Finally, due to the heritage from C the C++ language is in many
respects strongly tied to use of pointers"

--I would add a comma, and the word "the" should be added

"Finally, due to the heritage from C, the C++ language is in many
respects strongly tied to the use of pointers"

p.3
--"MingW"

--I believe it's "MinGW" (with a capital 'G')

p.6
--"Another example is an object within a std::vector, when that vector is
resized, e.g. when a new object added via push_back;"

--Add comma after "e.g.", add "is" to phrase

"... when that vector is resized, e.g., when a new object is added
via push_back;"

p.7
--"NRVO"

--You do not state what the 'N' stands for

--"Then the client code programmer, who knows more both about the client
code, the compiler and the acceptable efficiency"

--Remove the word "both", as it should be used when there are only two
things

p.9
--"That is, pNumbers is a pointer to a read-only IntVector. An IntVector
that can be read from, but not modified."

--I would change the period to a colon, since the second sentence has
no predicate

p.10
--"... IntVectors laid end to end in memory, a raw array of IntVectors,
and if so, how many?"

--I would add hyphens to "end to end", and delimit the "a raw array
of IntVectors" phrase with "i.e.,"

"... IntVectors laid end-to-end in memory, i.e., a raw array of
IntVectors, ..."

p.14
--"const is generally a restriction on operations, and you're not
allowed to remove a restriction on operations without at least telling
the compiler that you really mean it, the black book incantations I
hinted about."

--Add the word "of"

"... the black book of incantations I hinted about."

p.23
--Code listing

--Maybe I missed something, but the variable "e" (used in
stringFrom(e)) has not been declared.

--"it's a showstopper problem, let's tackle this latest problem first of
all."

--I would add the word "so"

"it's a showstopper problem, so let's tackle ..."

p.30
--Footnote i

--Does a static class method not count as "a type-specific function
that doesn't need to know anything about the object it's called on,
except the type"?

p.34
--Parts hierarchy

--I've also heard this described as a "HasA-hierarchy", which would
parallel your "IsA-hierarchy"

--"... and (3) calling delete on a Sum object in destroy, and
correspondingly for Product."

--I would delimit the comment about Product with a semicolon

"... calling delete on a Sum object in destroy; and correspondingly
for Product."

p.39
--"So given a pointer to an Expression object, if you call destroy on
that object the function implementation to execute will be the one"

--I would add a comma

"... if you call destroy on that object, the function ..."

p.43
--"or, the BinaryOperator destruction code is calling one of those
methods - for an implementation that more formally correct moves the
object's vtable pointer up again in the class hierarchy on
destruction, which hasn't been an issue in this implementation."

--I did not understand the phrase that starts with "for an
implementation..."

--"Any way it would indicate a serious bug"

--I would make "Any way" one word, and add a comma

"Anyway, it would indicate ..."

p.45
--"But in this subsection I focus only on what C++ can do for our
vtables and function pointers and function naming and downcasts and
call syntax, in short, for our method support"

--I would change a comma to a semicolon

"... and call syntax; in short, for our method support"

p.48
--Yellow box

--I think it would be clearer if you used commas/semicolons in
different places. I would either remove the comma before "uses a
vtable", or I would change the comma after that phrase to a
semicolon

either:
"A class that has at least one virtual member function uses a
vtable, and every object of that class has a vtable pointer."

or:
"A class that has at least one virtual member function, uses a
vtable; and every object of that class has a vtable pointer."

p.49
--"a C++ base class implementation of a virtual member function foo, and
its override in a derived class D, have the same name, namely just
foo, no name prefixes like we had to use when coding in C-style."

--I would change a comma to a semicolon

"... namely just foo; no name prefixes ..."

p.62
--"Resource Release is Destruction"

--I would call it "Destruction is Resource Release" (though I also
have never seen either RRID nor DIRR, so you can call it whatever
you like)

p.63
--"It also, first, allocates memory for the object from the heap, which
until now we've thought was primary."

--I did not understand the comment about "[thinking it] was primary"

p.64
--"The constructor call guarantee is not an absolute guarantee, and it's
not stated or referred to anywhere in the standard, but it's what the
detailed rules are designed to provide, it holds unless you use very
low-level language features"

--Change to semicolon

"it's what the detailed rules are designed to provide; it holds
unless ..."
Great work, Alf!

--
Marcus Kwok
Nov 22 '05 #47

P: n/a
Sorry to follow up to myself.

Marcus Kwok <ri******@gehennom.net> wrote:
Hi Alf, I made some notes for alpha3. However, most of them seem to
only be minor grammatical things that (IMHO) I think should be reworded.

p.48
--Yellow box

--I think it would be clearer if you used commas/semicolons in
different places. I would either remove the comma before "uses a
vtable", or I would change the comma after that phrase to a
semicolon

either:
"A class that has at least one virtual member function uses a
vtable, and every object of that class has a vtable pointer."

or:
"A class that has at least one virtual member function, uses a
vtable; and every object of that class has a vtable pointer."
On further review, I think the first alternative is the clearest.
p.62
--"Resource Release is Destruction"

--I would call it "Destruction is Resource Release" (though I also
have never seen either RRID nor DIRR, so you can call it whatever
you like)


Actually, I just found a few:
http://www.google.com/search?q=%22re...destruction%22

Far fewer results:
http://www.google.com/search?q=%22de...rce+release%22

--
Marcus Kwok
Nov 22 '05 #48

P: n/a
* Marcus Kwok:
Alf P. Steinbach <al***@start.no> wrote:
<url:
http://home.no.net/dubjai/win32cpptut/special/pointers/preview/pointers_01__alpha3.doc.pdf>.
Hi Alf, I made some notes for alpha3. However, most of them seem to
only be minor grammatical things that (IMHO) I think should be reworded.


Thanks. I've followed your recommendations to the letter (!), with two
exceptions; noted below.
[snip] p.7
--"NRVO"

--You do not state what the 'N' stands for
Named Return Value Optimization. Originally some compilers, such as (if
memory serves me right) g++ 2.95, offered a special syntax for naming
the return value of a function, and that was then called NRVO. Nowadays
NRVO instead stands for the case of

SomeType foo()
{
SomeType whatever;
...
return whatever;
}

where the 'return' value is a local variable. This special opportunity
for optimization (e.g. the compiler can arrange for a pointer to local
storage at the calling site to be passed to foo() so that the return
statement can copy construct the SomeType object directly into local
storage at the calling site, instead of going via a temporary) is
especially mentioned somewhere in the standard.
[snip] --"const is generally a restriction on operations, and you're not
allowed to remove a restriction on operations without at least telling
the compiler that you really mean it, the black book incantations I
hinted about."

--Add the word "of"

"... the black book of incantations I hinted about."
I meant the incantations, not the book. How to rephrase, if that's
still Bad English?

p.23
--Code listing

--Maybe I missed something, but the variable "e" (used in
stringFrom(e)) has not been declared.
Yep, sorry.

It should be 'e2xplus5'.
--"it's a showstopper problem, let's tackle this latest problem first of
all."

--I would add the word "so"

"it's a showstopper problem, so let's tackle ..."
There is a 'because' earlier in that long paragraph, so 'so' would be
misplaced, I think. "because of [this and that], which is a showstopper
problem, let's tackle...".
p.30
--Footnote i

--Does a static class method not count as "a type-specific function
that doesn't need to know anything about the object it's called on,
except the type"?
Yes, it does, but what I unsuccessfully tried to convey was the notion
of a virtual member function that doesn't need a 'this' pointer, i.e. a
member function where the actual implementation executed for a call on
an object o depends on the dynamic type of o; which is not the case for
a static member function.

Discussing that before virtual member functions have been introduced.

Which is difficult, especially in a footnote with limited space...

Suggestions?

[snip] p.43
--"or, the BinaryOperator destruction code is calling one of those
methods - for an implementation that more formally correct moves the
object's vtable pointer up again in the class hierarchy on
destruction, which hasn't been an issue in this implementation."

--I did not understand the phrase that starts with "for an
implementation..."
If you study the C-style implementation in that subsection, you'll see
that initialization effectively first sets the object's vtable pointer
to point to Expression's vtable, then to (say) BinaryOperator's vtable,
and finally to (say) Product's vtable, for initialization of a Product
object. That's just what the C++ OO support also does, to ensure that
one does not call a function in a derived class before initialization at
the derived class level has at least started; otherwise the derived
class function could be called and access uninitialized things, and
that's a not uncommon problem in e.g. Java and I think also in C#.
Destruction is opposite, and the C++ OO support then moves the vtable
pointer successively up in the inheritance chain, again to prevent
mishaps where a function otherwise could access uninitialized things.

Assuming (1) a vtable based C++ implementation and (2) that each class
at most inherits from one class.

Should I mention this, do you think? The document just gets longer and
longer...
[snip]
Great work, Alf!


Thanks, for very detailed corrections! I'll post a beta version Really
Really Soon Now.

The things added are roughly

1.3 Dynamically allocated objects versus others.
1.3.1 Ensure dynamic allocation by using C++ access specifiers &
friendship.
1.3.2 An aside on wrapping boost::shared_ptr (a.k.a.
std::tr1::shared_ptr).
1.3.3 Ensure that smart pointers are used, by overloading operator
new.
1.3.4 Combat slicing by removing access to copy assignment.
1.3.5 Value copying problems & possible solutions.
1.3.6 Cloning as a solution to ownership and aliasing problems.
1.3.7 Intentional sharing as a solution to ownership and aliasing
problems.
1.4 Basic serialization and de-serialization.
1.4.1 Functions that possibly don't succeed: introducing exception
handling.
1.4.2 Exception usage example: conversion between numeric values
and text.
1.4.3 A serialization format for hierarchical data structures.
1.4.4 De-serialization: the parser.
1.4.5 Serialization: the generator [currently unfinished].
1.5 Notes on C++ inheritance.
1.6 Summary [a little more to do].
1.7 Acknowledgements.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Nov 22 '05 #49

P: n/a
Alf P. Steinbach <al***@start.no> wrote:
* Marcus Kwok:
Hi Alf, I made some notes for alpha3. However, most of them seem to
only be minor grammatical things that (IMHO) I think should be reworded.


Thanks. I've followed your recommendations to the letter (!), with two
exceptions; noted below.

[snip]
--"const is generally a restriction on operations, and you're not
allowed to remove a restriction on operations without at least telling
the compiler that you really mean it, the black book incantations I
hinted about."

--Add the word "of"

"... the black book of incantations I hinted about."


I meant the incantations, not the book. How to rephrase, if that's
still Bad English?


How about, "telling the compiler that you really mean it, by using one
of the black book incantations ..."?
--"it's a showstopper problem, let's tackle this latest problem first of
all."

--I would add the word "so"

"it's a showstopper problem, so let's tackle ..."


There is a 'because' earlier in that long paragraph, so 'so' would be
misplaced, I think. "because of [this and that], which is a showstopper
problem, let's tackle...".


Hmm, the way I read it was like, "because of [this and that], it is a
showstopper problem, so let's tackle...", making the "so" sound better
to me. IMO I think it's clearer this way anyway. Or you could reword
it like, "because [this stuff] is not just extremely inconvenient, but
is a showstopper because it prevents us from [doing other stuff], let's
tackle..." (though I prefer the first way).
p.30
--Footnote i

--Does a static class method not count as "a type-specific function
that doesn't need to know anything about the object it's called on,
except the type"?


Yes, it does, but what I unsuccessfully tried to convey was the notion
of a virtual member function that doesn't need a 'this' pointer, i.e. a
member function where the actual implementation executed for a call on
an object o depends on the dynamic type of o; which is not the case for
a static member function.

Discussing that before virtual member functions have been introduced.

Which is difficult, especially in a footnote with limited space...

Suggestions?


Hmm, I guess what we're looking for is something like the notion of a
"static virtual member function"[0], which is not allowed. But since
you haven't introduced virtual member functions yet, I'm not sure of a
good way to explain this. Maybe you could mention this idea in the
footnote, but tell the reader to come back to it after you explain
virtual functions.
p.43
--"or, the BinaryOperator destruction code is calling one of those
methods - for an implementation that more formally correct moves the
object's vtable pointer up again in the class hierarchy on
destruction, which hasn't been an issue in this implementation."

--I did not understand the phrase that starts with "for an
implementation..."


If you study the C-style implementation in that subsection, you'll see
that initialization effectively first sets the object's vtable pointer
to point to Expression's vtable, then to (say) BinaryOperator's vtable,
and finally to (say) Product's vtable, for initialization of a Product
object. That's just what the C++ OO support also does, to ensure that
one does not call a function in a derived class before initialization at
the derived class level has at least started; otherwise the derived
class function could be called and access uninitialized things, and
that's a not uncommon problem in e.g. Java and I think also in C#.
Destruction is opposite, and the C++ OO support then moves the vtable
pointer successively up in the inheritance chain, again to prevent
mishaps where a function otherwise could access uninitialized things.

Assuming (1) a vtable based C++ implementation and (2) that each class
at most inherits from one class.

Should I mention this, do you think? The document just gets longer and
longer...


OK, I see now. In light of this, how about:

"or, the BinaryOperator destruction code is calling one of those
methods, which could occur on a (more formally correct) implementation
that moves the object's vtable pointer up again in the class hierarchy
on destruction (which hasn't been an issue in this implementation)."
Great work, Alf!


Thanks, for very detailed corrections! I'll post a beta version Really
Really Soon Now.


Great, I look forward to it.

[0]
What I mean by a "static virtual member function":

// NOT ALLOWED IN C++
class Base
{
public:
static virtual void doThis() { std::cout << "Base::doThis()\n"; }
};

class Derived : public Base
{
public:
static virtual void doThis() { std::cout << "Derived::doThis()\n"; }
};

int main()
{
Base* b = new Derived;
b->doThis();

return 0;
}

and have it resolve properly to Derived::doThis(). If I just make
doThis() static, it calls Base::doThis(), and if I just make it virtual,
it calls Derived::doThis() (as it should).

--
Marcus Kwok
Nov 22 '05 #50

53 Replies

This discussion thread is closed

Replies have been disabled for this discussion.