C++ function argument with 'class' keyword?

Discussion in 'C++' started by xhm, Jan 22, 2010.

  1. xhm

    xhm Guest

    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.
     
    xhm, Jan 22, 2010
    #1
    1. Advertising

  2. xhm

    Bo Persson Guest

    xhm wrote:
    > 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
     
    Bo Persson, Jan 23, 2010
    #2
    1. Advertising

  3. On Jan 23, 8:39 am, "Bo Persson" <> wrote:
    > xhm wrote:
    > > 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- Hide quoted text -
    >
    > - Show quoted text -


    Mr.Meyers said so
     
    **Group User**, Jan 23, 2010
    #3
  4. xhm

    James Kanze Guest

    On Jan 23, 2:34 pm, Pete Becker <> 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
     
    James Kanze, Jan 23, 2010
    #4
  5. xhm

    Öö Tiib Guest

    On Jan 23, 12:49 am, xhm <> wrote:
    > 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.
     
    Öö Tiib, Jan 24, 2010
    #5
  6. James Kanze wrote:

    > On Jan 23, 2:34 pm, Pete Becker <> 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), Jan 24, 2010
    #6
  7. Johannes Schaub (litb) wrote:

    > James Kanze wrote:
    >
    >> On Jan 23, 2:34 pm, Pete Becker <> wrote:
    >>> xhm wrote:
    >>> > 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).
    >

    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 :)
     
    Johannes Schaub (litb), Jan 24, 2010
    #7
  8. xhm

    James Kanze Guest

    On Jan 24, 4:29 pm, Pete Becker <> wrote:
    > James Kanze wrote:
    > > On Jan 23, 2:34 pm, Pete Becker <> 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, Jan 25, 2010
    #8
  9. xhm

    James Kanze Guest

    On Jan 24, 9:34 pm, "Johannes Schaub (litb)" <>
    wrote:
    > James Kanze wrote:
    > > On Jan 23, 2:34 pm, Pete Becker <> 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
     
    James Kanze, Jan 25, 2010
    #9
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Guy Robinson
    Replies:
    3
    Views:
    289
    John Hsu
    Jan 19, 2005
  2. Replies:
    6
    Views:
    468
    Peter Otten
    May 10, 2007
  3. Reckoner
    Replies:
    11
    Views:
    716
    Steven D'Aprano
    Jan 19, 2009
  4. AikidoGuy
    Replies:
    11
    Views:
    571
    Seebs
    Nov 21, 2011
  5. Replies:
    5
    Views:
    160
Loading...

Share This Page