34

I found the following code in a header file and the "BOOT" class is defined in another header file.

class BOOT* boot(void);

It looks like a declaration of a function, but it begins with class.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
rocmon
  • 535
  • 4
  • 11
  • 5
    It's a feature inherited from C. In C you must add the `struct`/`union` keyword whenever you refer to one. In C++, this is optional. Thus, `class BOOL` = `BOOL` – king_nak Nov 12 '20 at 09:34
  • 5
    In C++ is solely basically allows you to _declare_ a function type which returns a pointer of an (possibly incomplete) class type, but without having to forward declare the class type `BOOT` prior to the declaration. An alternative would be `class BOOT; // forward declaration` followed by `BOOT* boot();`., – dfrib Nov 12 '20 at 09:34
  • 2
    @king_nak They are not strictly the same, `class BOOL` also works as a forward declaration here. – Yksisarvinen Nov 12 '20 at 09:35
  • Compare with old-fashioned `typedef struct` constructs and give your brain a whirl ;) – Asteroids With Wings Nov 12 '20 at 18:21
  • @king_nak Another benefit of saying "class BOOL" is that -- as the cppreference quote cited by Rene points out -- it's valid even if somebody previously declared an (unrelated) typedef BOOT. – Peter - Reinstate Monica Nov 13 '20 at 13:41
  • This has already been answered here: https://stackoverflow.com/questions/28007165/class-keyword-in-variable-definition-in-c – Anouar Dec 02 '20 at 18:50

4 Answers4

35

This is an elaborated type specifier:

Elaborated type specifiers may be used to refer to a previously-declared class name (class, struct, or union) or to a previously-declared enum name even if the name was hidden by a non-type declaration. They may also be used to declare new class names.

https://en.cppreference.com/w/cpp/language/elaborated_type_specifier

Taking from answers of Artefacto and dfrib because it brings it on point: It is equivalent to:

class BOOT;
BOOT* boot(void);

In your example it essentially does a forward declaration of the class BOOT if it is not known yet. See this example struct Data* Data; from the same page:

struct Node {
    struct Node* Next; // OK: lookup of Node finds the injected-class-name
    struct Data* Data; // OK: declares type Data at global scope
                       // and also declares the data member Data
    friend class ::List; // error: cannot introduce a qualified name
    enum Kind* kind; // error: cannot introduce an enum
};
 
Data* p; // OK: struct Data has been declared
HolyBlackCat
  • 78,603
  • 9
  • 131
  • 207
Rene Oschmann
  • 676
  • 4
  • 16
  • Compare and contrast with: `class BOOT; using BOOT = int; BOOT* boot(void);` – Deduplicator Nov 13 '20 at 13:34
  • Is this useful beyond saving a line? I would be confused by this syntax, too, and would prefer the two declarations separately for readability. – ahota Nov 13 '20 at 18:49
  • @ahota: The documentation says "Elaborated type specifiers may be used to refer to a previously-declared class name (class, struct, or union) or to a previously-declared enum name even if the name was hidden by a non-type declaration." (see https://stackoverflow.com/questions/57865891 for details) It has it's place. I personally prefer being more explicit, i.e. I would avoid the syntax, if it is not needed. However, this is a matter of personal preference. – Rene Oschmann Nov 13 '20 at 20:19
20

It is the same as this:

class BOOT;
BOOT* boot(void);

So it's a pointer to class BOOT, but with a declaration of the class as well. The class need not be defined at this point.

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
Artefacto
  • 96,375
  • 17
  • 202
  • 225
12

What does “class classname* funcname(void) ”mean in C++?

It is a function declaration.

It looks like a declaration of a function, but it begins with "class".

class classname* is the return type of the function. class classname is an elaborated type specifier.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
eerorika
  • 232,697
  • 12
  • 197
  • 326
8

Different forms of forward declarations used to introduce class-name:s into its scope

In C++ you may declare a function type whose return type contains a class type that is defined elsewhere, as long as you either explicitly forward declare the class type prior to the function declaration:

class BOOT;
BOOT* boot();

but you may likewise place the forward declaration in-line in the function declaration:

class BOOT* boot();

This is one of the places where, possibly somewhat unexpectedly, forward declarations can be used. Another example is as in the template argument list for a type-template parameter:

template<typename T>
struct Identity { using type = T; };

using IdentityBoot = Identity<struct BOOT>;
//                            ^^^^^^^^^^^ also a forward declaration

// OK
BOOT* boot();

// OK
typename IdentityBoot::type* another_boot();

Elaborated type specifiers can be used to introduce names into its scope

Formally, it's an elaborated-type-specifier, governed by [dcl.type.elab],

elaborated-type-specifier:
    class-key [...]
    [...]

that is used to, as per [class]/1, make a class-name that is introduced into the scope where the elaborated-type-specifier is used [emphasis mine]:

A class is a type. Its name becomes a class-name ([class.name]) within its scope. [...]

Class-specifiers and elaborated-type-specifiers are used to make class-names.

dfrib
  • 70,367
  • 12
  • 127
  • 192