3

When and why should we use the 'struct' keyword when declaring a class pointer variable in C++?

I've seen this in embedded environments so I suspect that this is some kind of hold over from C. I've seen plenty of explanations on when to use the 'struct' keyword when declaring a struct object as it relates to namespaces in C (here), but I wasn't able to find anyone talking about why one might use it when declaring a class pointer variable.

Example, in CFoo.h:

class CFoo
{
public:
    int doStuff();
};

inline Foo::doStuff()
{
    return 7;
}

And later in a different class:

void CBar::interesting()
{
    struct CFoo *pCFoo;

    // Go on to do something interesting with pCFoo...
}
5
  • 4
    @πάνταῥεῖ Once again, bad dupe. That one is about C. This question is about C++. The distinction is literally the entire point of the question. Please stop. Commented Aug 21, 2019 at 13:50
  • Closing this as a dupe to a C question isn't a good idea. In C this is purely a matter of style. Commented Aug 21, 2019 at 13:50
  • @Lundin In C++ it's a matter of style. In C it's mandatory. Commented Aug 21, 2019 at 13:50
  • @LightnessRacesinOrbit Not if you use typedef, which is by far the most common style in C. Commented Aug 21, 2019 at 13:51
  • @Lundin Well, that's cheating! This question is not about using type aliases, but about using the actual names of types and the limitations/constraints/requirements thereof. Yes, you can use a type alias to bypass said requirements in C. Yes, that's extremely common. Though, as a side note, things like struct tm are not given this treatment so they're extremely common too - even in C++ code lol Commented Aug 21, 2019 at 13:53

4 Answers 4

7

There's rarely a reason to do this: it's a fallover from C and in this case the programmer is simply being sentimental - perhaps it's there as a quest for readability. That said, it can be used in place of forward declarations.

In some instances you might need to disambiguate, but that's not the case here. One example where disambiguation would be necessary is

class foo{};

int main()
{
    int foo;
    class foo* pf1;
    struct foo* pf2;
}

Note that you can use class and struct interchangeably. You can use typename too which can be important when working with templates. The following is valid C++:

class foo{};

int main()
{    
    class foo* pf1;
    struct foo* pf2;
    typename foo* pf3;
}
Sign up to request clarification or add additional context in comments.

7 Comments

Do note, though, that VS in particular has a propensity to warn about keyword-switching, even though foo is simply "a class" regardless of the syntax you originally used to define it!
@LightnessRacesinOrbit: Doesn't MSVC fail compilation if you forward declare with a struct then define with a class?
With whatever is its equivalent of -Werror I'm sure yes :)
(Real answer: I don't actually know; possibly!)
@Bathsheba Oh yeah, it's worse than I thought - forgot about that!
|
5

There are two reasons to do this.

The first one is if we are going to introduce a new type in the scope using an elaborated name. That is in this definition

void CBar::interesting()
{
    struct CFoo *pCFoo;

    // Go on to do something interesting with pCFoo...
}

the new type struct CFoo is introduced in the scope provided that it is not yet declared. The pointer may point to an incomplete type because pointers themselves are complete types.

The second one is when a name of a class is hidden by a declaration of a function or a variable. In this case we again need to use an elaborated type name.

Here are some examples

#include <iostream>

void CFoo( const class CFoo * c ) { std::cout << ( const void * )c << '\n'; }

class CFoo
{
public:
    int doStuff();
};


int main() 
{
    class CFoo c1;

    return 0;
}

Or

#include <iostream>

class CFoo
{
public:
    int doStuff();
};

void CFoo( void ) { std::cout << "I am hidding the class CGoo!\n"; }

int main() 
{
    class CFoo c1;

    return 0;
}

Comments

2

In C, two different styles are the most common:

  • typedef struct { ... } s; with variables declared as s name;.
  • struct s { ... }; with variables declared as struct s name;

In C++ you don't need to typedef to omit the struct keyword, so the former style is far more in line with the C++ type system and classes, making it the most common style in C++.

But then there are not many cases in C++ when you actually want to use struct instead of class in the first place - structs are essentially classes with all members public by default.

5 Comments

"structs are essentially classes with all members public by default" Classes are classes are classes. C++ does not have structs. (+1 though)
@LightnessRacesinOrbit There was some point in time when STL functors were encouraged to be written as structs rather than classes, for some mysterious reason. Though that might very well have been in the pre C++98 days.
I use struct to define functors, usually, because they don't tend to have state so I only have to write private: rarely (as opposed to public: frequently) and frankly it just "looks more lightweight" (even though that's a lie). But they're still classes :)
@LightnessRacesinOrbit I think I picked it up once upon a time from the odd little book "Designing components with the C++ STL", published year 2000. The author (Breymann) gives this weird rationale for writing functors as structs: "The word struct saves the public label. Everything can be public, because the class has no data to be protected." Which is true, I suppose... and he called it a class even back then.
Hmm, if I'm reading that right, his rationale is "everything can be public, so you can use a struct", as if to say "everything in a struct must be public". Thing is, that's not true.
2

The reason for this may be as simple as not having to include a header file whose contents aren't needed other than for announcing that CFoo names a type. That's often done with a forward declaration:

class CFoo;
void f(CFoo*);

but it can also be done on the fly:

void f(struct CFoo*);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.