Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

C++ function argument with 'class' keyword?

0 views
Skip to first unread message

xhm

unread,
Jan 22, 2010, 5:49:34 PM1/22/10
to
Hi

I am reading some C++ code written by others, and notice a method in a
class has a prototype that has an argument with 'class' keyword, like

1) bool test(class A &mya);

where A is a class name and mya is an object name.

I am wondering the meaning of the 'class' keyword in this declaration.
I would think it can be declared as:

2) bool test(A &mya)

what's the difference between 1) and 2). Or the 'class' keyword in 1)
actually is not necessary? I tried to search on the Internet but
didn't find an answer.

Thanks for any explanation on this in advance.

Bo Persson

unread,
Jan 22, 2010, 8:39:19 PM1/22/10
to

There is no difference.

I believe this is allowed because in C you would have to write

bool test(struct A*)

or use a typedef name for the struct.


Bo Persson


**Group User**

unread,
Jan 22, 2010, 11:41:42 PM1/22/10
to
> Bo Persson- Hide quoted text -
>
> - Show quoted text -

Mr.Meyers said so

Pete Becker

unread,
Jan 23, 2010, 9:34:26 AM1/23/10
to
xhm wrote:
>
> 1) bool test(class A &mya);
>
> where A is a class name and mya is an object name.
>
> I am wondering the meaning of the 'class' keyword in this declaration.
> I would think it can be declared as:
>

It means that A is the name of a class (or struct or union, but don't
worry about that wrinkle for now).

> 2) bool test(A &mya)
>
> what's the difference between 1) and 2). Or the 'class' keyword in 1)
> actually is not necessary? I tried to search on the Internet but
> didn't find an answer.
>

The difference is that without more, the first is valid and the second
isn't. In order for the second one to compile there has to be a previous
declaration of A.

bool test(A &mya); // error: A not defined
bool test(class A &mya); // OK: A names a class

------------------

class A;
bool test(A &mya); // OK
bool test(class A &mya); // OK

------------------

class A
{
// whatever...
};
bool test(A& mya); // OK
bool test(class A& mya); // OK

------------------

bool test(class A& mya); // OK

On the other hand, the declaration within a function prototype only
applies within the prototype:

bool test(class A& mya); // OK
bool also_test(A& may); // error: A not defined

This kind of on-the-fly declaration isn't used much any more.

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

James Kanze

unread,
Jan 23, 2010, 6:41:51 PM1/23/10
to
On Jan 23, 2:34 pm, Pete Becker <p...@versatilecoding.com> wrote:
> xhm wrote:

> > 1) bool test(class A &mya);

> > where A is a class name and mya is an object name.

> > I am wondering the meaning of the 'class' keyword in this
> > declaration. I would think it can be declared as:

> It means that A is the name of a class (or struct or union,
> but don't worry about that wrinkle for now).

Are you sure about union? I don't have my copy of the standard
(or any draft, for that matter) handy to check, but I seem to
remember that unions got special handling in this regard. (A
union is a class... except when it isn't.)

> > 2) bool test(A &mya)

> > what's the difference between 1) and 2). Or the 'class'
> > keyword in 1) actually is not necessary? I tried to search
> > on the Internet but didn't find an answer.

> The difference is that without more, the first is valid and
> the second isn't. In order for the second one to compile there
> has to be a previous declaration of A.

> bool test(A &mya); // error: A not defined
> bool test(class A &mya); // OK: A names a class

IIRC, it's more subtle than that. The second names a class in
function prototype scope. And I don't see where you're going to
be able to define a class in function prototype scope, so the
second effectively names a class which can't be defined.

(From memory. And this is really the sort of question where I
miss not having my copy of the standard handy, because name
lookup isn't always that trivial.)

> ------------------

> class A;
> bool test(A &mya); // OK
> bool test(class A &mya); // OK

> ------------------

> class A
> {
> // whatever...};

> bool test(A& mya); // OK
> bool test(class A& mya); // OK

> ------------------

> bool test(class A& mya); // OK

> On the other hand, the declaration within a function prototype
> only applies within the prototype:

> bool test(class A& mya); // OK
> bool also_test(A& may); // error: A not defined

> This kind of on-the-fly declaration isn't used much any more.

Except in header files which have to be used in both C and C++
(in which case, of course, it's "struct A*", and not "class
A&").

--
James Kanze

Öö Tiib

unread,
Jan 23, 2010, 9:05:52 PM1/23/10
to

In C you had to write something like that:

struct A { int i; };
typedef struct A A;

In C++ the typedef is done automatically with classes, structs, enums
and unions. So you do not need to write it. You *may* write it since
it is defining again something that is already defined, the compilers
may not object.

Result of typedef is that both 'A' and 'struct A' mean same thing. So
when A is a class, there are no difference between lines 1) and 2) of
yours. You get compiler error if you say 'class A' about enum A. You
may get only a warning if you say 'class A' about struct A since
struct is class and compilers have to compile it by standard.

Pete Becker

unread,
Jan 24, 2010, 11:29:28 AM1/24/10
to
James Kanze wrote:
> On Jan 23, 2:34 pm, Pete Becker <p...@versatilecoding.com> wrote:
>
>> The difference is that without more, the first is valid and
>> the second isn't. In order for the second one to compile there
>> has to be a previous declaration of A.
>
>> bool test(A &mya); // error: A not defined
>> bool test(class A &mya); // OK: A names a class
>
> IIRC, it's more subtle than that. The second names a class in
> function prototype scope.

Sigh. See below:

>
>> On the other hand, the declaration within a function prototype
>> only applies within the prototype:
>
>> bool test(class A& mya); // OK
>> bool also_test(A& may); // error: A not defined
>

--

Johannes Schaub (litb)

unread,
Jan 24, 2010, 4:34:24 PM1/24/10
to
James Kanze wrote:

> On Jan 23, 2:34 pm, Pete Becker <p...@versatilecoding.com> wrote:
>> xhm wrote:
>
>> > 1) bool test(class A &mya);
>
>> > where A is a class name and mya is an object name.
>
>> > I am wondering the meaning of the 'class' keyword in this
>> > declaration. I would think it can be declared as:
>
>> It means that A is the name of a class (or struct or union,
>> but don't worry about that wrinkle for now).
>
> Are you sure about union? I don't have my copy of the standard
> (or any draft, for that matter) handy to check, but I seem to
> remember that unions got special handling in this regard. (A
> union is a class... except when it isn't.)
>

I think you have the IsClass and IsClassType concepts of c++0x in mind,
which made a difference between union and struct/class. But in general,
unions indeed are classes (so for instance, it's indeed possible to have
"union templates" without anything explicitly stating that in the Standard).
What is not allowed is "enum A &mya".

>> > 2) bool test(A &mya)
>
>> > what's the difference between 1) and 2). Or the 'class'
>> > keyword in 1) actually is not necessary? I tried to search
>> > on the Internet but didn't find an answer.
>
>> The difference is that without more, the first is valid and
>> the second isn't. In order for the second one to compile there
>> has to be a previous declaration of A.
>
>> bool test(A &mya); // error: A not defined
>> bool test(class A &mya); // OK: A names a class
>
> IIRC, it's more subtle than that. The second names a class in
> function prototype scope. And I don't see where you're going to
> be able to define a class in function prototype scope, so the
> second effectively names a class which can't be defined.
>

That's only the case in C. In C++ such a class will be a member of the
enclosing namespace, as said by 3.3.2/6. Granted, it just says that the
class-name is declared in the enclosing namespace. But its intent seems that
the class is also a member of that namespace (so, scope of a name determines
identity of the entity referred to, here).

In C you will only be able to define such a type by having a struct
declaration for the new type placed into another TU, because the first
declaration and the second declaration of the tag identifier will refer to
different entities if you try to define the type in the same TU. If you
define it in another TU and then in that other TU define the function, then
both functions across the TU are of compatible types (not the same - but
that's not necessary) and behavior is well defined. Scopes are not used for
randomly determining identity of an entitiy in C (but merely linkage does -
and identifiers of types have no linkage).

This code works on comeau and GCC (getting back to C++ again), and indeed
shows that the class is a member of the enclosing namespace, rather than a
local class or something else:

void f(class X);
class X { };
void f(X x) { }

int main() {
&f; // f is not an overloaded function
}


> (From memory. And this is really the sort of question where I
> miss not having my copy of the standard handy, because name
> lookup isn't always that trivial.)
>

Yeah, name lookup and especially rules about declarative regions and scopes
and identity are confusing in my opinion :(


>> ------------------
>
>> class A;
>> bool test(A &mya); // OK
>> bool test(class A &mya); // OK
>
>> ------------------
>
>> class A
>> {
>> // whatever...};
>
>> bool test(A& mya); // OK
>> bool test(class A& mya); // OK
>
>> ------------------
>
>> bool test(class A& mya); // OK
>
>> On the other hand, the declaration within a function prototype
>> only applies within the prototype:
>
>> bool test(class A& mya); // OK
>> bool also_test(A& may); // error: A not defined
>
>> This kind of on-the-fly declaration isn't used much any more.
>
> Except in header files which have to be used in both C and C++
> (in which case, of course, it's "struct A*", and not "class
> A&").
>

Tho i believe most people will go the easy way and do "struct A;" at the
start of those function declarations, rather than sprinkling the code with
those in-line forward declarations :)

Johannes Schaub (litb)

unread,
Jan 24, 2010, 5:00:41 PM1/24/10
to
Johannes Schaub (litb) wrote:

I'm wrong on the last sentence. You can do the following in C:

struct X;
struct X { int a; };

And both declarations declare tags for the same type. This is not because of
linkage, though, but because of additional constraints that struct specifier
in the same scope with the same tag declare the same type. In the following
the specifiers appear in different scopes, so they specify different types,
and they are not compatible since they are not declared in different TUs:

void f(struct X x);
void f(struct X { int a; } x) { }

That's why we need to place the definition in another TU, so that type
compatibility rules then make both types compatible and make it well
defined.

Alright, i just wanted to see how this behaves in C. I'm sorry for the
offtopicness :)


James Kanze

unread,
Jan 24, 2010, 8:27:28 PM1/24/10
to
On Jan 24, 4:29 pm, Pete Becker <p...@versatilecoding.com> wrote:
> James Kanze wrote:
> > On Jan 23, 2:34 pm, Pete Becker <p...@versatilecoding.com> wrote:

> >> The difference is that without more, the first is valid and
> >> the second isn't. In order for the second one to compile there
> >> has to be a previous declaration of A.

> >> bool test(A &mya); // error: A not defined
> >> bool test(class A &mya); // OK: A names a class

> > IIRC, it's more subtle than that. The second names a class in
> > function prototype scope.

> Sigh. See below:

Sorry, I wrote that before seeing below...

> >> On the other hand, the declaration within a function prototype
> >> only applies within the prototype:

> >> bool test(class A& mya); // OK
> >> bool also_test(A& may); // error: A not defined

And after seeing this, I meant to drop the article. I must have
hit the wrong button.

--
James Kanze

James Kanze

unread,
Jan 24, 2010, 9:01:15 PM1/24/10
to
On Jan 24, 9:34 pm, "Johannes Schaub (litb)" <schaub-johan...@web.de>
wrote:

> James Kanze wrote:
> > On Jan 23, 2:34 pm, Pete Becker <p...@versatilecoding.com> wrote:
> >> xhm wrote:

> >> > 1) bool test(class A &mya);

> >> > where A is a class name and mya is an object name.

> >> > I am wondering the meaning of the 'class' keyword in this
> >> > declaration. I would think it can be declared as:

> >> It means that A is the name of a class (or struct or union,
> >> but don't worry about that wrinkle for now).

> > Are you sure about union? I don't have my copy of the
> > standard (or any draft, for that matter) handy to check, but
> > I seem to remember that unions got special handling in this
> > regard. (A union is a class... except when it isn't.)

> I think you have the IsClass and IsClassType concepts of c++0x in mind,

Certainly not, since I'm not familiar with them.

> which made a difference between union and struct/class. But in
> general, unions indeed are classes (so for instance, it's
> indeed possible to have "union templates" without anything
> explicitly stating that in the Standard).

As I said, unions are classes, except when they aren't. A union
cannot have a base class, for example, nor can it have virtual
functions. I have a vague memory that there was also a
(specific) requirement that unions must be declared with union,
and non-union classes with struct or class, but I can't find it
in the 1998 version of the standard on my backup, and I can't
access the 2003 version. (The backup is from a Linux system,
and the name of the 2003 version is 14882:2003.pdf. I'm
currently under Windows, and it doesn't seem to like this
name:-).)

Anyway, it's a memory. I'm not sure it's correct. (But I seem
to recall thinking like you, and having someone point the
restriction out to me.)

> What is not allowed is "enum A &mya".

Nor things with typedef.

> >> > 2) bool test(A &mya)

> >> > what's the difference between 1) and 2). Or the 'class'
> >> > keyword in 1) actually is not necessary? I tried to search
> >> > on the Internet but didn't find an answer.

> >> The difference is that without more, the first is valid and
> >> the second isn't. In order for the second one to compile
> >> there has to be a previous declaration of A.

> >> bool test(A &mya); // error: A not defined
> >> bool test(class A &mya); // OK: A names a class

> > IIRC, it's more subtle than that. The second names a class
> > in function prototype scope. And I don't see where you're
> > going to be able to define a class in function prototype
> > scope, so the second effectively names a class which can't
> > be defined.

> That's only the case in C. In C++ such a class will be a
> member of the enclosing namespace, as said by 3.3.2/6.
> Granted, it just says that the class-name is declared in the
> enclosing namespace. But its intent seems that the class is
> also a member of that namespace (so, scope of a name
> determines identity of the entity referred to, here).

In the 1998 version of the standard, there is no 3.3.2/6, but
§3.3.3 is quite clear that there is a "function prototype
scope", and §3.4.3 makes it clear that if there is no previous
delcaration of the class, the qualified name is treated as a
declaration. In scope.

The only case I'm aware of where a name is declared in a scope
other than that of the declaration is in friend declarations.

--
James Kanze

Pete Becker

unread,
Jan 25, 2010, 6:51:04 AM1/25/10
to

I hate it when I do that. <g>

0 new messages