C++ function argument with 'class' keyword?

X

xhm

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.
 
B

Bo Persson

xhm said:
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.

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
 
G

**Group User**

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- Hide quoted text -

- Show quoted text -

Mr.Meyers said so
 
J

James Kanze

xhm wrote:
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.)
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&").
 
Ö

Öö Tiib

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.

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.
 
J

Johannes Schaub (litb)

James said:
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".
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 :(

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 :)
 
J

Johannes Schaub (litb)

Johannes said:
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).
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 :)
 
J

James Kanze

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.
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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,982
Messages
2,570,185
Members
46,736
Latest member
AdolphBig6

Latest Threads

Top