27

I often see stuff like this:

class SomeClass {
public:
    void someMethod();
private:
    int someMember;
};

This seems totally unnatural to me (the same applies to case-statements when using switch). I expected something like this, when I started using C++ (it's been a long time since then, but I am still wondering):

class SomeClass {
    public:
        void someMethod();
    private:
        int someMember;
};

Is there a funded reason to break (otherwise) consistent indentation rules?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
jwueller
  • 30,582
  • 4
  • 66
  • 70
  • 2
    People are lazy and sometimes have bad formatting. – Justin Meiners Nov 28 '10 at 23:26
  • 1
    vim will indent that code, and switch statements, as you expect. – Bill Lynch Nov 28 '10 at 23:28
  • 31
    @sharth: To be fair, you can probably configure `vim` to cook breakfast for you if you want. – Billy ONeal Nov 28 '10 at 23:33
  • Because, any other way than the former (with 2 rather than 4 spaces for indent--NOT tabs) is evil and will get you excommunicated. – Edward Strange Nov 28 '10 at 23:39
  • 3
    As a matter of fact, I do indent in exactly this style. It looks way more natural. Btw. I also indent case statements with 2 levels. – rioki Nov 29 '10 at 12:36
  • effectively a (time-travelling) dupe of [Why the strange indentation on switch statements?](https://stackoverflow.com/questions/4509039/why-the-strange-indentation-on-switch-statements) – underscore_d Dec 22 '21 at 15:21
  • Despite the voting, this version of the question seems a little better to me. Of course, both are really too opinion-based for Stack Overflow by modern interpretation. – Karl Knechtel Jun 26 '22 at 22:46

10 Answers10

37

Increasing indentation normally reflects entry to a new nested scope, whereas both access specifiers and switch case statements don't vary the scope (the same is true of labels generally). Access specifiers can be optional in that you may start implementing a class or struct and have all members only need the implied access (i.e. private and public respectively), but then the code evolves and you need to add a specifier for the non-implied-access members: is it really worth having to suddenly change the indentation on all members? Again, there's no nested scope, so I think that would be actively misleading.

If you work on fixed-width terminals and wrap your lines accordingly, reindenting's a pain. But, it is useful to have the access specifiers stand out from the members, which means putting them back to the left somewhere - either in line with the class keyword or part-way there.

Personally, I do this:

class X
{
  public:
    int member_function()
    {
        switch (expression)
        {
          case X:
            return 6;

          default:
          {
            int n = get_value() / 6;
            return n * n;
          }
        }
    }

  private:
    int member_variable_;
};

Why do I not indent code for each case further? I can't claim what I do is particularly logical, but factors include:

  • I don't want to deemphasise the general switch/case indentation, as visually communicating the extent of the switch is important to quickly understanding the code
  • I'm happy just to put the { and } around existing case code - more like a comment "hey, I need a scope" - rather than feeling compelling to indent everything further, which doesn't make much sense even to me but kind of feels right - I like having the code for each case line up
  • some compilers do warn if you introduce new variables inside a case statement without introducing a scope, even if there are no cases when the variable is later used potentially uninitialised
  • I'm an 80-column coder generally, with 4 space indents normally, so being inside a switch - and thus obviously a function - means remaining columns are valuable.

Same for class/struct:

  • I want to scan the left column and quickly find the end of the class, or easily count the small classes on screen or in a printout; access specifiers at exactly the same indentation level deemphasise the class keyword, but it does help to have them visually distinct from the members (if the class/struct is more than a few lines, I also add a blank line beforehand)
  • I don't want to change existing class/struct member indentation when I introduce a private or protected specifier

In conclusion: lots of small factors go into developing people's indentation preferences, and if you want to be a C++ programmer in a corporate environment - especially a contractor - you just have to go with the flow and be able to change your own style sometimes too (e.g. I'm stuck in camelCaseLand right now, with public member variables starting with an uppercase letter - yikes!). Don't sweat it - it's not worth it.

Tony Delroy
  • 102,968
  • 15
  • 177
  • 252
  • @Tony: I think that i am really flexible in terms of code-style (even though i have a preferred style, of course), but i was interested in the reasoning behind this formatting decisions. Thanks for this insightful post. It cleared that up a lot. – jwueller Nov 29 '10 at 01:20
  • @Tony: "4 space indents normally" --> personally I use 2, it's sufficient to introduce an indentation level I think, 4 seems a waste :) – Matthieu M. Nov 29 '10 at 09:52
  • 2
    I agree on the thing about scopes. I find it more important that an indentation level deeper also means a scope deeper. – Mephane Nov 29 '10 at 09:57
  • @Matthieu: at other times (and in other languages, e.g. Ruby) I've used 2 spaces - works fine too, though it does leave the "half-an-indent" thing looking a little less visually distinguished. There's definitely a balance between wasting space, gently discouraging excessive nesting (which is often a sign of a need to refactor), and clear visual differentiation. No exact answers. – Tony Delroy Nov 30 '10 at 01:25
  • @Tony: ah, I don't use the "half-an-indent" thing, guess that's why I've found 4 spaces wasteful. "half-an-indent" of a single space must not be easily spotted. – Matthieu M. Nov 30 '10 at 07:43
  • Interesting. I think of indentation as an indication of control flow. I'd never considered it as an indication of scope. Of course, it's really a hybrid: Indentation under a `case` isn't a new scope, and creating (and indenting) a block solely to create a limited scope doesn't affect control. – Michael Carman Feb 20 '12 at 20:57
14

The access specifiers are really just labels (as in those used by goto). People generally don't indent labels, or outdent them one level with respect to the surrounding code. So I would say this is not inconsistent at all.

The Standard also uses this style for access specifiers. Example from Chapter 10, paragraph 2:

class Base {
public:
  int a, b, c;
};
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
John Dibling
  • 99,718
  • 31
  • 186
  • 324
  • 4
    I think you'll probably find it was downvoted because access specifiers have _nothing_ to do with labels, other than the fact they both have a colon at the end. But bravo for insulting someone whose motives you know nothing about - you sure put them in their place :-) Actually, on those rare occasions where I _use_ labels, I indent them as well. – paxdiablo Nov 28 '10 at 23:34
  • 2
    @pax: I have recently read from someone of authority that the access specifiers were intended to look & feel like labels. I didnt just pull this out of my hat. I am however unable to locate this reference now... – John Dibling Nov 28 '10 at 23:37
  • 1
    @John i think @pax was more on the formal meaning of "label", ignoring the fact you are using it in the non-formal meaning. – Johannes Schaub - litb Nov 29 '10 at 00:15
  • 1
    I'd add to your answer that labels are generally *out-dented* one tab with respect to the code they are labeling. – user207421 Nov 29 '10 at 02:59
8

Imagine such a class definition:

class SomeClass {
    void ImplicitlyPrivateMethod();
public:
    void someMethod();
private:
    int someMember;
};

With the style of indentation you propose, one would need to change this into

class SomeClass {
        void ImplicitlyPrivateMethod();
    public:
        void someMethod();
    private:
        int someMember;
};

(which looks not so nice to many people, especially if the "implicit" section is long enough).


I personally prefer half-indentation of such specifiers:

class SomeClass {
    void ImplicitlyPrivateMethod();
  public:
    void someMethod();
  private:
    int someMember;
};

But this is a matter of personal taste.

Vlad
  • 35,022
  • 6
  • 77
  • 199
  • 4
    Here I would say, don't write definitions without a access specifier before it. I know it is valid code, but they just belong into classes. – rioki Nov 29 '10 at 12:38
  • 2
    @Sean: when defining a `struct`, usually no access modifiers are used at all. Do you propose to have different indentation rules for `struct`s? – Vlad Nov 30 '10 at 02:28
  • As a matter of fact, no. Classes and structs have the same indentation, only the successors are on level the class statement is on. – rioki Dec 08 '10 at 09:20
  • Interesting discussion. Personally, whether for a struct or class I use consistent indentation, but I always put public members before private. So I'd move `ImplicitlyPrivateMethod()` down under the `private:` access specified (and it wouldn't be Implicit any longer). structs could still have private members at the bottom... for example, helper functions for the public member functions / still logically distinct from classes in not providing comprehensive encapsulation and typically being intended for more localised use within an implementation, rather than across API boundaries. – Tony Delroy Jun 08 '12 at 16:29
8

As with many other things, it is important not to mistake the rule with the purpose. The purpose of indentation is making code clearer and easier to read by providing an extra visual hint on what belongs where. Now, in the particular cases you mention, together with namespaces, in many cases the extra indentation does not help in readability. The cases in a switch can be understood as if-elses, where you would not add the extra indentation. The cases are block delimiters similar to the curly braces.

switch ( var ) {  
case 1:          // if ( var == 1 ) {
   code;
case 2:          // } else if ( var == 2 ) {
   code;
}

At class level, access modifiers can be considered to be block delimiters at the same level that the class braces. Adding an extra level of indentation does not make the code clearer:

class test {
public:
   void foo();
private:
   int member;
};

The same way goes with namespaces, where some people avoid indenting the whole namespace level. In all three cases, there is no clear advantage in adding the extra indentation and if you abide to short code lines (80/100 characters) and big enough indentation levels (8 or even 4 characters) then there might be an advantage to not indenting.

Personally, I never indent case or accessor modifiers, in the case of namespaces, it depends... a namespace that covers the whole source file will most probably not be indented, while namespaces that only take part of the source file will be indented --the rationale is that in the former case it adds no actual value, while in the second it does.

David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489
6

Two possible reasons:

  • that's how Bjarne Stroustrup indents them in his books

  • most text editors indent them that way automatically

6

Because public and private are labels which don't introduce a new scope, I prefer not to give them any special indentation, thus:

class foo {
    public:
    void something();
    void something_else();

    private:
    int top_secret;
};

This way, the consistent indentation rule is "indentation equals scope".

Karl Knechtel
  • 62,466
  • 11
  • 102
  • 153
4

It's all about scoping and grouping of branches. If these are not affected, then do not add an indentation level.

Take for instance the following:

if( test == 1 ) {
    action1( );
} else if( test == 2 ) {
    action2( );
} else {
    action3( );
}

Take note of the levels of the statement blocks. Now re-write it as a case statement with indented cases:

switch( test ) {
    case 1:
        action1( );
        break;
    case 2:
        action2( );
        break;
    default:
        action3( );
        break;
}

This does the exact same functionally, yet the indentations don't match of my actions. And I think it is this inconsistency that finally made me change to dropping the extra spurious indentation. (Even though I don't mind the half-indenting proposed by others, mind you.)

Marius
  • 3,372
  • 1
  • 30
  • 36
1

There are very few access modifier lines per class, and most editors color modifiers differently from everything else. They stand out plenty on their own, so adding tabs is unnecessary.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
robert
  • 33,242
  • 8
  • 53
  • 74
0

As mentioned earlier (though argued for non-indented access modifiers), access modifiers form logical blocks. While these are at the same level as the class braces, they are special.

Thus it's useful to have indentation to clearly show where each block starts and ends.

I personally think it makes the code clearer. Others will dissagree.

This is a rather subjective question.

Srdjant
  • 203
  • 1
  • 2
  • 5
-1

Most editors indent them automatically. For me, I leave them as they are in small classes or small files or short switch statements, but for long ones or a long file with many long switch statements I use more indentation for easier readability.

I sometimes do this which I feel is as old style:

Class CClass
    {
            CClass();
            ~CClass();
        Public:
            int a;
        Private:
            int b;
     };
CClass::CClass
      {
           TODO code;
      }

This sometimes makes it easier when a file may contain more than 20 or 50 functions, so you can easily spot the beginning of every function.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Dr. Mina Mounir
  • 314
  • 3
  • 13