SlideShare a Scribd company logo
1 of 78
Download to read offline
C++ Idioms by Example, lesson 1
                           I
             Introducing some very basic C++ idioms, rules, guidelines and best practices
                           h
                           a

                                                              Olve Maudal
                                                             oma@pvv.org

                                                            November 2008




Disclaimer: most of the items I will discuss here are indeed idioms and conventions of the C++ language, something that most experts will
agree on. However some of the items are based on an ecolect – a programming style that is unique for a limited group of developers. There
are also a few items based on my idiolect, which is a programming style that I believe in. And you may argue that one or two things I
suggest here are just plain idiotic...

My intention is not to tell you how to do C++ programming. I hope to use this presentation as a catalyst for discussion, therefor I have also
included some controversial issues.

Ignite your flamethrower. Choose your battles!
Please criticise this program.

~/myprog/foo.hpp                                                     ~/myprog/foo.cpp
namespace bar {                                                      #include <iostream>
  class Foo {                                                        #include "foo.hpp"
     int _value;
     int my_magic(int a, int b);                                     using namespace std;
  public:
     Foo(int seed);                                                  namespace bar {
     int calc(int number = 7);                                         Foo::Foo(int seed) {
     int getValue() {                                                    _value = seed;
       return _value;                                                  }
     }
     void print(char* prefix);                                          int Foo::my_magic(int a, int b) {
  };                                                                      return a + b - 3 + 8 - 5;
}                                                                       }

                                                                        int Foo::calc(int number) {
                                                                          int result = my_magic(_value, number);
                                                                          _value += result;
~/myprog/main.cpp                                                         return result;
                                                                        }
#include "foo.hpp"
                                                                void Foo::print(char *prefix) {
int main() {                                                        cout << prefix << _value << "n";
  bar::Foo foo(2);                                              }
  char * prefix = "the answer=";                             }
  for(int i=0; i<4; i++) {
    foo.calc(i);

                                    Please criticise this program
  }
  foo.print(prefix);
  return 0;
}                             Spend 5-10 minutes to read through the code. Imagine that this is a piece of code that
                              you found in a larger codebase. Criticise everything you see,

                                    ... apart from the fact that it is a contrived, incorrect and stupid program that does not
                                    do anything useful, and is probably better written in Python as print “the
$ cd ~/myprog                       answer=42” (and do not spend time on the implmentation of my_magic)
$ g++ foo.cpp main.cpp && ./a.out
the answer=43
What do you see in this code?

        Happiness?
or trouble?
I see trouble.

It looks like the code has been written by someone
with little experience in C++, or even worse, by
someone who does not care...

Large amount of this kind of code will make your
codebase rot.

But, once you start to believe - it is time to defeat the
deteriorating agents
~/myprog/foo.hpp                    ~/myprog/foo.cpp
namespace bar {                     #include <iostream>
  class Foo {                       #include "foo.hpp"
     int _value;
     int my_magic(int a, int b);    using namespace std;
  public:
     Foo(int seed);                 namespace bar {
     int calc(int number = 7);        Foo::Foo(int seed) {
     int getValue() {                   _value = seed;
       return _value;                 }
     }
     void print(char* prefix);          int Foo::my_magic(int a, int b) {
  };                                      return a + b - 3 + 8 - 5;
}                                       }

                                        int Foo::calc(int number) {
                                          int result = my_magic(_value, number);
                                          _value += result;
~/myprog/main.cpp                         return result;
                                        }
#include "foo.hpp"
                                        void Foo::print(char *prefix) {
int main() {                              cout << prefix << _value << "n";
  bar::Foo foo(2);                      }
  char * prefix = "the answer=";    }
  for(int i=0; i<4; i++) {
    foo.calc(i);
  }
  foo.print(prefix);
  return 0;
}




$ cd ~/myprog
$ g++ foo.cpp main.cpp && ./a.out
the answer=43
1. always compile with high warning level, and treat warnings as errors

~/myprog/foo.hpp                            ~/myprog/foo.cpp
namespace bar {                             #include <iostream>
  class Foo {                               #include "foo.hpp"
     int _value;
     int my_magic(int a, int b);            using namespace std;
  public:
     Foo(int seed);                         namespace bar {
     int calc(int number = 7);                Foo::Foo(int seed) {
     int getValue() {                           _value = seed;
       return _value;                         }
     }
     void print(char* prefix);                  int Foo::my_magic(int a, int b) {
  };                                              return a + b - 3 + 8 - 5;
}                                               }

                                                int Foo::calc(int number) {
                                                  int result = my_magic(_value, number);
                                                  _value += result;
~/myprog/main.cpp                                 return result;
                                                }
#include "foo.hpp"
                                                void Foo::print(char *prefix) {
int main() {                                      cout << prefix << _value << "n";
  bar::Foo foo(2);                              }
  char * prefix = "the answer=";            }
  for(int i=0; i<4; i++) {
    foo.calc(i);
  }
  foo.print(prefix);
  return 0;
}




$ cd ~/myprog
$ g++ -Wall -Wextra -pedantic -Werror foo.cpp main.cpp && ./a.out
the answer=43
2. always use tools to support the building process

~/myprog/foo.hpp                                 ~/myprog/foo.cpp
namespace bar {                                  #include <iostream>
  class Foo {                                    #include "foo.hpp"
     int _value;
     int my_magic(int a, int b);                 using namespace std;
  public:
     Foo(int seed);
                       ~/myprog/Makefile
     int calc(int number = 7);
                                                 namespace bar {
                                                   Foo::Foo(int seed) {
     int getValue() {                                 _value = seed;
       return _value; CPPFLAGS=-Wall       -Wextra } -pedantic -Werror
     }                 LDFLAGS=
     void print(char* prefix);                       int Foo::my_magic(int a, int b) {
  };                                                   return a + b - 3 + 8 - 5;
}                      all: myprog                   }

                                                     int Foo::calc(int number) {
                  myprog: foo.o main.o   int result = my_magic(_value,               number);

~/myprog/main.cpp    $(CXX) -o $@ $(LDFLAGS) $+ result;
                                         _value +=
                                         return result;
                                                     }
#include "foo.hpp"
                     clean:                void Foo::print(char *prefix)           {
int main() {            rm -f foo.o main.o myprog prefix << _value <<
                                             cout <<                               "n";
  bar::Foo foo(2);                                   }
  char * prefix = "the answer=";                 }
  for(int i=0; i<4; i++) {
    foo.calc(i);
  }
  foo.print(prefix);
  return 0;
}




$ cd ~/myprog
$ make
$ ./myprog
the answer=43
3. do not _prefix member variables, use postfix_ if you must

~/myprog/foo.hpp                            ~/myprog/foo.cpp
namespace bar {                             #include <iostream>
  class Foo {                               #include "foo.hpp"
     int _value;
     int my_magic(int a, int b);            using namespace std;
  public:
     Foo(int seed);                         namespace bar {
     int calc(int number = 7);                Foo::Foo(int seed) {
     int getValue() {                           _value = seed;
       return _value;                         }
     }
     void print(char* prefix);                  int Foo::my_magic(int a, int b) {
  };                                              return a + b - 3 + 8 - 5;
}                                               }

                                                int Foo::calc(int number) {
                                                  int result = my_magic(_value, number);
                                                  _value += result;
~/myprog/main.cpp                                 return result;
                                                }
#include "foo.hpp"
                                                void Foo::print(char *prefix) {
int main() {                                      cout << prefix << _value << "n";
  bar::Foo foo(2);                              }
  char * prefix = "the answer=";            }
  for(int i=0; i<4; i++) {
    foo.calc(i);
  }
  foo.print(prefix);
  return 0;
}
3. do not _prefix member variables, use postfix_ if you must

~/myprog/foo.hpp                            ~/myprog/foo.cpp
namespace bar {                             #include <iostream>
  class Foo {                               #include "foo.hpp"
     int value_;
     int my_magic(int a, int b);            using namespace std;
  public:
     Foo(int seed);                         namespace bar {
     int calc(int number = 7);                Foo::Foo(int seed) {
     int getValue() {                           value_ = seed;
       return value_;                         }
     }
     void print(char* prefix);                  int Foo::my_magic(int a, int b) {
  };                                              return a + b - 3 + 8 - 5;
}                                               }

                                                int Foo::calc(int number) {
                                                  int result = my_magic(value_, number);
                                                  value_ += result;
~/myprog/main.cpp                                 return result;
                                                }
#include "foo.hpp"
                                                void Foo::print(char *prefix) {
int main() {                                      cout << prefix << value_ << "n";
  bar::Foo foo(2);                              }
  char * prefix = "the answer=";            }
  for(int i=0; i<4; i++) {
    foo.calc(i);
  }
  foo.print(prefix);
  return 0;
}
4. public stuff should be declared first, then the private stuff

~/myprog/foo.hpp                               ~/myprog/foo.cpp
namespace bar {                                #include <iostream>
  class Foo {                                  #include "foo.hpp"
     int value_;
     int my_magic(int a, int b);               using namespace std;
  public:
     Foo(int seed);                            namespace bar {
     int calc(int number = 7);                   Foo::Foo(int seed) {
     int getValue() {                              value_ = seed;
       return value_;                            }
     }
     void print(char* prefix);                     int Foo::my_magic(int a, int b) {
  };                                                 return a + b - 3 + 8 - 5;
}                                                  }

                                                   int Foo::calc(int number) {
                                                     int result = my_magic(value_, number);
                                                     value_ += result;
~/myprog/main.cpp                                    return result;
                                                   }
#include "foo.hpp"
                                                   void Foo::print(char *prefix) {
int main() {                                         cout << prefix << value_ << "n";
  bar::Foo foo(2);                                 }
  char * prefix = "the answer=";               }
  for(int i=0; i<4; i++) {
    foo.calc(i);
  }
  foo.print(prefix);
  return 0;
}
4. public stuff should be declared first, then the private stuff

~/myprog/foo.hpp                               ~/myprog/foo.cpp
namespace bar {                                #include <iostream>
  class Foo {                                  #include "foo.hpp"
  public:
     Foo(int seed);                            using namespace std;
     int calc(int number = 7);
     int getValue() {                          namespace bar {
       return value_;                            Foo::Foo(int seed) {
     }                                             value_ = seed;
     void print(char* prefix);                   }
  private:
     int value_;                                   int Foo::my_magic(int a, int b) {
     int my_magic(int a, int b);                     return a + b - 3 + 8 - 5;
  };                                               }
}
                                                   int Foo::calc(int number) {
                                                     int result = my_magic(value_, number);
                                                     value_ += result;
~/myprog/main.cpp                                    return result;
                                                   }
#include "foo.hpp"
                                                   void Foo::print(char *prefix) {
int main() {                                         cout << prefix << value_ << "n";
  bar::Foo foo(2);                                 }
  char * prefix = "the answer=";               }
  for(int i=0; i<4; i++) {
    foo.calc(i);
  }
  foo.print(prefix);
  return 0;
}
5. single argument constructors should usually be explicit

~/myprog/foo.hpp                            ~/myprog/foo.cpp
namespace bar {                             #include <iostream>
  class Foo {                               #include "foo.hpp"
  public:
     Foo(int seed);                         using namespace std;
     int calc(int number = 7);
     int getValue() {                       namespace bar {
       return value_;                         Foo::Foo(int seed) {
     }                                          value_ = seed;
     void print(char* prefix);                }
  private:
     int value_;                                int Foo::my_magic(int a, int b) {
     int my_magic(int a, int b);                  return a + b - 3 + 8 - 5;
  };                                            }
}
                                                int Foo::calc(int number) {
                                                  int result = my_magic(value_, number);
                                                  value_ += result;
~/myprog/main.cpp                                 return result;
                                                }
#include "foo.hpp"
                                                void Foo::print(char *prefix) {
int main() {                                      cout << prefix << value_ << "n";
  bar::Foo foo(2);                              }
  char * prefix = "the answer=";            }
  for(int i=0; i<4; i++) {
    foo.calc(i);
  }
  foo.print(prefix);
  return 0;
}
5. single argument constructors should usually be explicit

~/myprog/foo.hpp                            ~/myprog/foo.cpp
namespace bar {                             #include <iostream>
  class Foo {                               #include "foo.hpp"
  public:
     explicit Foo(int seed);                using namespace std;
     int calc(int number = 7);
     int getValue() {                       namespace bar {
       return value_;                         Foo::Foo(int seed) {
     }                                          value_ = seed;
     void print(char* prefix);                }
  private:
     int value_;                                int Foo::my_magic(int a, int b) {
     int my_magic(int a, int b);                  return a + b - 3 + 8 - 5;
  };                                            }
}
                                                int Foo::calc(int number) {
                                                  int result = my_magic(value_, number);
                                                  value_ += result;
~/myprog/main.cpp                                 return result;
                                                }
#include "foo.hpp"
                                                void Foo::print(char *prefix) {
int main() {                                      cout << prefix << value_ << "n";
  bar::Foo foo(2);                              }
  char * prefix = "the answer=";            }
  for(int i=0; i<4; i++) {
    foo.calc(i);
  }
  foo.print(prefix);
  return 0;
}
6. initialize the state of the object properly

~/myprog/foo.hpp                                 ~/myprog/foo.cpp
namespace bar {                                  #include <iostream>
  class Foo {                                    #include "foo.hpp"
  public:
     explicit Foo(int seed);                     using namespace std;
     int calc(int number = 7);
     int getValue() {                            namespace bar {
       return value_;                              Foo::Foo(int seed) {
     }                                               value_ = seed;
     void print(char* prefix);                     }
  private:
     int value_;                                     int Foo::my_magic(int a, int b) {
     int my_magic(int a, int b);                       return a + b - 3 + 8 - 5;
  };                                                 }
}
                                                     int Foo::calc(int number) {
                                                       int result = my_magic(value_, number);
                                                       value_ += result;
~/myprog/main.cpp                                      return result;
                                                     }
#include "foo.hpp"
                                                     void Foo::print(char *prefix) {
int main() {                                           cout << prefix << value_ << "n";
  bar::Foo foo(2);                                   }
  char * prefix = "the answer=";                 }
  for(int i=0; i<4; i++) {
    foo.calc(i);
  }
  foo.print(prefix);
  return 0;
}
6. initialize the state of the object properly

~/myprog/foo.hpp                                 ~/myprog/foo.cpp
namespace bar {                                  #include <iostream>
  class Foo {                                    #include "foo.hpp"
  public:
     explicit Foo(int seed);                     using namespace std;
     int calc(int number = 7);
     int getValue() {                            namespace bar {
       return value_;                              Foo::Foo(int seed) : value_(seed) {
     }                                             }
     void print(char* prefix);
  private:                                           int Foo::my_magic(int a, int b) {
     int value_;                                       return a + b - 3 + 8 - 5;
     int my_magic(int a, int b);                     }
  };
}                                                    int Foo::calc(int number) {
                                                       int result = my_magic(value_, number);
                                                       value_ += result;
                                                       return result;
~/myprog/main.cpp                                    }
#include "foo.hpp"                                   void Foo::print(char *prefix) {
                                                       cout << prefix << value_ << "n";
int main() {                                         }
  bar::Foo foo(2);                               }
  char * prefix = "the answer=";
  for(int i=0; i<4; i++) {
    foo.calc(i);
  }
  foo.print(prefix);
  return 0;
}
7. use a consistent naming convention, camelCase or under_score

~/myprog/foo.hpp                         ~/myprog/foo.cpp
namespace bar {                          #include <iostream>
  class Foo {                            #include "foo.hpp"
  public:
     explicit Foo(int seed);             using namespace std;
     int calc(int number = 7);
     int getValue() {                    namespace bar {
       return value_;                      Foo::Foo(int seed) : value_(seed) {
     }                                     }
     void print(char* prefix);
  private:                                   int Foo::my_magic(int a, int b) {
     int value_;                               return a + b - 3 + 8 - 5;
     int my_magic(int a, int b);             }
  };
}                                            int Foo::calc(int number) {
                                               int result = my_magic(value_, number);
                                               value_ += result;
                                               return result;
~/myprog/main.cpp                            }
#include "foo.hpp"                           void Foo::print(char *prefix) {
                                               cout << prefix << value_ << "n";
int main() {                                 }
  bar::Foo foo(2);                       }
  char * prefix = "the answer=";
  for(int i=0; i<4; i++) {
    foo.calc(i);
  }
  foo.print(prefix);
  return 0;
}
7. use a consistent naming convention, camelCase or under_score

~/myprog/foo.hpp                         ~/myprog/foo.cpp
namespace bar {                          #include <iostream>
  class Foo {                            #include "foo.hpp"
  public:
     explicit Foo(int seed);             using namespace std;
     int calc(int number = 7);
     int getValue() {                    namespace bar {
       return value_;                      Foo::Foo(int seed) : value_(seed) {
     }                                     }
     void print(char* prefix);
  private:                                   int Foo::myMagic(int a, int b) {
     int value_;                               return a + b - 3 + 8 - 5;
     int myMagic(int a, int b);              }
  };
}                                            int Foo::calc(int number) {
                                               int result = myMagic(value_, number);
                                               value_ += result;
                                               return result;
~/myprog/main.cpp                            }
#include "foo.hpp"                           void Foo::print(char *prefix) {
                                               cout << prefix << value_ << "n";
int main() {                                 }
  bar::Foo foo(2);                       }
  char * prefix = "the answer=";
  for(int i=0; i<4; i++) {
    foo.calc(i);
  }
  foo.print(prefix);
  return 0;
}
8. do not prefix queries and modifiers with get/set

~/myprog/foo.hpp                             ~/myprog/foo.cpp
namespace bar {                              #include <iostream>
  class Foo {                                #include "foo.hpp"
  public:
     explicit Foo(int seed);                 using namespace std;
     int calc(int number = 7);
     int getValue() {                        namespace bar {
       return value_;                          Foo::Foo(int seed) : value_(seed) {
     }                                         }
     void print(char* prefix);
  private:                                       int Foo::myMagic(int a, int b) {
     int value_;                                   return a + b - 3 + 8 - 5;
     int myMagic(int a, int b);                  }
  };
}                                                int Foo::calc(int number) {
                                                   int result = myMagic(value_, number);
                                                   value_ += result;
                                                   return result;
~/myprog/main.cpp                                }
#include "foo.hpp"                               void Foo::print(char *prefix) {
                                                   cout << prefix << value_ << "n";
int main() {                                     }
  bar::Foo foo(2);                           }
  char * prefix = "the answer=";
  for(int i=0; i<4; i++) {
    foo.calc(i);
  }
  foo.print(prefix);
  return 0;
}
8. do not prefix queries and modifiers with get/set

~/myprog/foo.hpp                             ~/myprog/foo.cpp
namespace bar {                              #include <iostream>
  class Foo {                                #include "foo.hpp"
  public:
     explicit Foo(int seed);                 using namespace std;
     int calc(int number = 7);
     int value() {                           namespace bar {
       return value_;                          Foo::Foo(int seed) : value_(seed) {
     }                                         }
     void print(char* prefix);
  private:                                       int Foo::myMagic(int a, int b) {
     int value_;                                   return a + b - 3 + 8 - 5;
     int myMagic(int a, int b);                  }
  };
}                                                int Foo::calc(int number) {
                                                   int result = myMagic(value_, number);
                                                   value_ += result;
                                                   return result;
~/myprog/main.cpp                                }
#include "foo.hpp"                               void Foo::print(char *prefix) {
                                                   cout << prefix << value_ << "n";
int main() {                                     }
  bar::Foo foo(2);                           }
  char * prefix = "the answer=";
  for(int i=0; i<4; i++) {
    foo.calc(i);
  }
  foo.print(prefix);
  return 0;
}
9. do not import namespaces

~/myprog/foo.hpp                   ~/myprog/foo.cpp
namespace bar {                    #include <iostream>
  class Foo {                      #include "foo.hpp"
  public:
     explicit Foo(int seed);       using namespace std;
     int calc(int number = 7);
     int value() {                 namespace bar {
       return value_;                Foo::Foo(int seed) : value_(seed) {
     }                               }
     void print(char* prefix);
  private:                             int Foo::myMagic(int a, int b) {
     int value_;                         return a + b - 3 + 8 - 5;
     int myMagic(int a, int b);        }
  };
}                                      int Foo::calc(int number) {
                                         int result = myMagic(value_, number);
                                         value_ += result;
                                         return result;
~/myprog/main.cpp                      }
#include "foo.hpp"                     void Foo::print(char *prefix) {
                                         cout << prefix << value_ << "n";
int main() {                           }
  bar::Foo foo(2);                 }
  char * prefix = "the answer=";
  for(int i=0; i<4; i++) {
    foo.calc(i);
  }
  foo.print(prefix);
  return 0;
}
9. do not import namespaces

~/myprog/foo.hpp                   ~/myprog/foo.cpp
namespace bar {                    #include <iostream>
  class Foo {                      #include "foo.hpp"
  public:
     explicit Foo(int seed);       namespace bar {
     int calc(int number = 7);       Foo::Foo(int seed) : value_(seed) {
     int value() {                   }
       return value_;
     }                                 int Foo::myMagic(int a, int b) {
     void print(char* prefix);           return a + b - 3 + 8 - 5;
  private:                             }
     int value_;
     int myMagic(int a, int b);        int Foo::calc(int number) {
  };                                     int result = myMagic(value_, number);
}                                        value_ += result;
                                         return result;
                                       }

~/myprog/main.cpp                      void Foo::print(char *prefix) {
                                         std::cout << prefix << value_ << "n";
#include "foo.hpp"                     }
                                   }
int main() {
  bar::Foo foo(2);
  char * prefix = "the answer=";
  for(int i=0; i<4; i++) {
    foo.calc(i);
  }
  foo.print(prefix);
  return 0;
}
10. query functions should be declared const

~/myprog/foo.hpp                           ~/myprog/foo.cpp
namespace bar {                            #include <iostream>
  class Foo {                              #include "foo.hpp"
  public:
     explicit Foo(int seed);               namespace bar {
     int calc(int number = 7);               Foo::Foo(int seed) : value_(seed) {
     int value() {                           }
       return value_;
     }                                         int Foo::myMagic(int a, int b) {
     void print(char* prefix);                   return a + b - 3 + 8 - 5;
  private:                                     }
     int value_;
     int myMagic(int a, int b);                int Foo::calc(int number) {
  };                                             int result = myMagic(value_, number);
}                                                value_ += result;
                                                 return result;
                                               }

~/myprog/main.cpp                              void Foo::print(char *prefix) {
                                                 std::cout << prefix << value_ << "n";
#include "foo.hpp"                             }
                                           }
int main() {
  bar::Foo foo(2);
  char * prefix = "the answer=";
  for(int i=0; i<4; i++) {
    foo.calc(i);
  }
  foo.print(prefix);
  return 0;
}
10. query functions should be declared const

~/myprog/foo.hpp                           ~/myprog/foo.cpp
namespace bar {                            #include <iostream>
  class Foo {                              #include "foo.hpp"
  public:
     explicit Foo(int seed);               namespace bar {
     int calc(int number = 7);               Foo::Foo(int seed) : value_(seed) {
     int value() const {                     }
       return value_;
     }                                         int Foo::myMagic(int a, int b) {
     void print(char* prefix) const;             return a + b - 3 + 8 - 5;
  private:                                     }
     int value_;
     int myMagic(int a, int b);                int Foo::calc(int number) {
  };                                             int result = myMagic(value_, number);
}                                                value_ += result;
                                                 return result;
                                               }

~/myprog/main.cpp                              void Foo::print(char *prefix) const {
                                                 std::cout << prefix << value_ << "n";
#include "foo.hpp"                             }
                                           }
int main() {
  bar::Foo foo(2);
  char * prefix = "the answer=";
  for(int i=0; i<4; i++) {
    foo.calc(i);
  }
  foo.print(prefix);
  return 0;
}
11. non-const functions are modifiers

~/myprog/foo.hpp                        ~/myprog/foo.cpp
namespace bar {                         #include <iostream>
  class Foo {                           #include "foo.hpp"
  public:
     explicit Foo(int seed);            namespace bar {
     int calc(int number = 7);            Foo::Foo(int seed) : value_(seed) {
     int value() const {                  }


                                                                               ?
       return value_;
     }                                      int Foo::myMagic(int a, int b) {
     void print(char* prefix) const;          return a + b - 3 + 8 - 5;
  private:                                  }
     int value_;
     int myMagic(int a, int b);             int Foo::calc(int number) {
  };                                          int result = myMagic(value_, number);
}                                             value_ += result;
                                              return result;
                                            }

~/myprog/main.cpp                           void Foo::print(char *prefix) const {
                                              std::cout << prefix << value_ << "n";
#include "foo.hpp"                          }
                                        }
int main() {
  bar::Foo foo(2);
  char * prefix = "the answer=";
  for(int i=0; i<4; i++) {
    foo.calc(i);
  }
  foo.print(prefix);
  return 0;
}
12. prefer free-standing functions

~/myprog/foo.hpp                       ~/myprog/foo.cpp
namespace bar {                        #include <iostream>
  class Foo {                          #include "foo.hpp"
  public:
     explicit Foo(int seed);           namespace bar {
     int calc(int number = 7);           Foo::Foo(int seed) : value_(seed) {
     int value() const {                 }
       return value_;
     }                                     int Foo::myMagic(int a, int b) {
     void print(char* prefix) const;         return a + b - 3 + 8 - 5;
  private:                                 }
     int value_;
     int myMagic(int a, int b);            int Foo::calc(int number) {
  };                                         int result = myMagic(value_, number);
}                                            value_ += result;
                                             return result;
                                           }

~/myprog/main.cpp                          void Foo::print(char *prefix) const {
                                             std::cout << prefix << value_ << "n";
#include "foo.hpp"                         }
                                       }
int main() {
  bar::Foo foo(2);
  char * prefix = "the answer=";
  for(int i=0; i<4; i++) {
    foo.calc(i);
  }
  foo.print(prefix);
  return 0;
}
12. prefer free-standing functions

~/myprog/foo.hpp                       ~/myprog/foo.cpp
namespace bar {                        #include <iostream>
  class Foo {                          #include "foo.hpp"
  public:
     explicit Foo(int seed);           namespace bar {
     int calc(int number = 7);           Foo::Foo(int seed) : value_(seed) {
     int value() const {                 }
       return value_;
     }                                     int Foo::myMagic(int a, int b) {
     void print(char* prefix) const;         return a + b - 3 + 8 - 5;
  private:                                 }
     int value_;
     int myMagic(int a, int b);            int Foo::calc(int number) {
  };                                         int result = myMagic(value_, number);
}                                            value_ += result;
                                             return result;
                                           }

~/myprog/main.cpp                          void Foo::print(char *prefix) const {
                                             std::cout << prefix << value_ << "n";
#include "foo.hpp"                         }
                                       }
int main() {
  bar::Foo foo(2);
  char * prefix = "the answer=";
  for(int i=0; i<4; i++) {
    foo.calc(i);
  }
  foo.print(prefix);
  return 0;
}
12. prefer free-standing functions

~/myprog/foo.hpp                       ~/myprog/foo.cpp
namespace bar {                        #include <iostream>
  class Foo {                          #include "foo.hpp"
  public:
     explicit Foo(int seed);           namespace bar {
     int calc(int number = 7);           Foo::Foo(int seed) : value_(seed) {
     int value() const {                 }
       return value_;
     }                                     int myMagic(int a, int b) {
     void print(char* prefix) const;         return a + b - 3 + 8 - 5;
  private:                                 }
     int value_;
  };                                       int Foo::calc(int number) {
}                                            int result = myMagic(value_, number);
                                             value_ += result;
                                             return result;
                                           }

~/myprog/main.cpp                          void Foo::print(char *prefix) const {
                                             std::cout << prefix << value_ << "n";
#include "foo.hpp"                         }
                                       }
int main() {
  bar::Foo foo(2);
  char * prefix = "the answer=";
  for(int i=0; i<4; i++) {
    foo.calc(i);
  }
  foo.print(prefix);
  return 0;
}
13. use anonymous namespaces for private free-standing functions

~/myprog/foo.hpp                         ~/myprog/foo.cpp
namespace bar {                          #include <iostream>
  class Foo {                            #include "foo.hpp"
  public:
     explicit Foo(int seed);             namespace bar {
     int calc(int number = 7);             Foo::Foo(int seed) : value_(seed) {
     int value() const {                   }
       return value_;
     }                                       int myMagic(int a, int b) {
     void print(char* prefix) const;           return a + b - 3 + 8 - 5;
  private:                                   }
     int value_;
  };                                         int Foo::calc(int number) {
}                                              int result = myMagic(value_, number);
                                               value_ += result;
                                               return result;
                                             }

~/myprog/main.cpp                            void Foo::print(char *prefix) const {
                                               std::cout << prefix << value_ << "n";
#include "foo.hpp"                           }
                                         }
int main() {
  bar::Foo foo(2);
  char * prefix = "the answer=";
  for(int i=0; i<4; i++) {
    foo.calc(i);
  }
  foo.print(prefix);
  return 0;
}
13. use anonymous namespaces for private free-standing functions

~/myprog/foo.hpp                         ~/myprog/foo.cpp
namespace bar {                          #include <iostream>
  class Foo {                            #include "foo.hpp"
  public:
     explicit Foo(int seed);             namespace {
     int calc(int number = 7);             int myMagic(int a, int b) {
     int value() const {                     return a + b - 3 + 8 - 5;
       return value_;                      }
     }                                   }
     void print(char* prefix) const;
  private:                               namespace bar {
     int value_;                           Foo::Foo(int seed) : value_(seed) {
  };                                       }
}
                                             int Foo::calc(int number) {
                                               int result = myMagic(value_, number);
                                               value_ += result;
                                               return result;
~/myprog/main.cpp                            }
#include "foo.hpp"                           void Foo::print(char *prefix) const {
                                               std::cout << prefix << value_ << "n";
int main() {                                 }
  bar::Foo foo(2);                       }
  char * prefix = "the answer=";
  for(int i=0; i<4; i++) {
    foo.calc(i);
  }
  foo.print(prefix);
  return 0;
}
14. do not inline stuff in the class definition

~/myprog/foo.hpp                                  ~/myprog/foo.cpp
namespace bar {                                   #include <iostream>
  class Foo {                                     #include "foo.hpp"
  public:
     explicit Foo(int seed);                      namespace {
     int calc(int number = 7);                      int myMagic(int a, int b) {
     int value() const {                              return a + b - 3 + 8 - 5;
       return value_;                               }
     }                                            }
     void print(char* prefix) const;
  private:                                        namespace bar {
     int value_;                                    Foo::Foo(int seed) : value_(seed) {
  };                                                }
}
                                                      int Foo::calc(int number) {
                                                        int result = myMagic(value_, number);
                                                        value_ += result;
                                                        return result;
~/myprog/main.cpp                                     }
#include "foo.hpp"                                    void Foo::print(char *prefix) const {
                                                        std::cout << prefix << value_ << "n";
int main() {                                          }
  bar::Foo foo(2);                                }
  char * prefix = "the answer=";
  for(int i=0; i<4; i++) {
    foo.calc(i);
  }
  foo.print(prefix);
  return 0;
}
14. do not inline stuff in the class definition

~/myprog/foo.hpp                                  ~/myprog/foo.cpp
namespace bar {                                   #include <iostream>
  class Foo {                                     #include "foo.hpp"
  public:
     explicit Foo(int seed);                      namespace {
     int calc(int number = 7);                      int myMagic(int a, int b) {
     int value() const;                               return a + b - 3 + 8 - 5;
     void print(char* prefix) const;                }
  private:                                        }
     int value_;
  };                                              namespace bar {
                                                    Foo::Foo(int seed) : value_(seed) {
    inline int Foo::value() const {                 }
      return value_;
    }                                                 int Foo::calc(int number) {
}                                                       int result = myMagic(value_, number);
                                                        value_ += result;
                                                        return result;
~/myprog/main.cpp                                     }
#include "foo.hpp"                                    void Foo::print(char *prefix) const {
                                                        std::cout << prefix << value_ << "n";
int main() {                                          }
  bar::Foo foo(2);                                }
  char * prefix = "the answer=";
  for(int i=0; i<4; i++) {
    foo.calc(i);
  }
  foo.print(prefix);
  return 0;
}
15. by default keep your stuff in the implementation file

~/myprog/foo.hpp                             ~/myprog/foo.cpp
namespace bar {                              #include <iostream>
  class Foo {                                #include "foo.hpp"
  public:
     explicit Foo(int seed);                 namespace {
     int calc(int number = 7);                 int myMagic(int a, int b) {
     int value() const;                          return a + b - 3 + 8 - 5;
     void print(char* prefix) const;           }
  private:                                   }
     int value_;
  };                                         namespace bar {
                                               Foo::Foo(int seed) : value_(seed) {
    inline int Foo::value() const {            }
      return value_;
    }                                            int Foo::calc(int number) {
}                                                  int result = myMagic(value_, number);
                                                   value_ += result;
                                                   return result;
~/myprog/main.cpp                                }
#include "foo.hpp"                               void Foo::print(char *prefix) const {
                                                   std::cout << prefix << value_ << "n";
int main() {                                     }
  bar::Foo foo(2);                           }
  char * prefix = "the answer=";
  for(int i=0; i<4; i++) {
    foo.calc(i);
  }
  foo.print(prefix);
  return 0;
}
15. by default keep your stuff in the implementation file

~/myprog/foo.hpp                             ~/myprog/foo.cpp
namespace bar {                              #include <iostream>
  class Foo {                                #include "foo.hpp"
  public:
     explicit Foo(int seed);                 namespace {
     int calc(int number = 7);                 int myMagic(int a, int b) {
     int value() const;                          return a + b - 3 + 8 - 5;
     void print(char* prefix) const;           }
  private:                                   }
     int value_;
  };                                         namespace bar {
}                                              Foo::Foo(int seed) : value_(seed) {
                                               }

                                                 int Foo::calc(int number) {
                                                   int result = myMagic(value_, number);
                                                   value_ += result;
                                                   return result;
~/myprog/main.cpp                                }
#include "foo.hpp"                               int Foo::value() const {
                                                   return value_;
int main() {                                     }
  bar::Foo foo(2);
  char * prefix = "the answer=";                 void Foo::print(char *prefix) const {
  for(int i=0; i<4; i++) {                         std::cout << prefix << value_ << "n";
    foo.calc(i);                                 }
  }                                          }
  foo.print(prefix);
  return 0;
}
16. avoid member functions that both modifies and queries

~/myprog/foo.hpp                          ~/myprog/foo.cpp
namespace bar {                           #include <iostream>
  class Foo {                             #include "foo.hpp"
  public:
     explicit Foo(int seed);              namespace {
     int calc(int number = 7);              int myMagic(int a, int b) {
     int value() const;                       return a + b - 3 + 8 - 5;
     void print(char* prefix) const;        }
  private:                                }
     int value_;
  };                                      namespace bar {
}                                           Foo::Foo(int seed) : value_(seed) {
                                            }

                                              int Foo::calc(int number) {
                                                int result = myMagic(value_, number);
                                                value_ += result;
                                                return result;
~/myprog/main.cpp                             }
#include "foo.hpp"                            int Foo::value() const {
                                                return value_;
int main() {                                  }
  bar::Foo foo(2);
  char * prefix = "the answer=";              void Foo::print(char *prefix) const {
  for(int i=0; i<4; i++) {                      std::cout << prefix << value_ << "n";
    foo.calc(i);                              }
  }                                       }
  foo.print(prefix);
  return 0;
}
16. avoid member functions that both modifies and queries

~/myprog/foo.hpp                          ~/myprog/foo.cpp
namespace bar {                           #include <iostream>
  class Foo {                             #include "foo.hpp"
  public:
     explicit Foo(int seed);              namespace {
     void calc(int number = 7);             int myMagic(int a, int b) {
     int value() const;                       return a + b - 3 + 8 - 5;
     void print(char* prefix) const;        }
  private:                                }
     int value_;
  };                                      namespace bar {
}                                           Foo::Foo(int seed) : value_(seed) {
                                            }

                                              void Foo::calc(int number) {
                                                value_ += myMagic(value_, number);
                                              }

~/myprog/main.cpp                             int Foo::value() const {
                                                return value_;
#include "foo.hpp"                            }
int main() {                                  void Foo::print(char *prefix) const {
  bar::Foo foo(2);                              std::cout << prefix << value_ << "n";
  char * prefix = "the answer=";              }
  for(int i=0; i<4; i++) {                }
    foo.calc(i);
  }
  foo.print(prefix);
  return 0;
}
17. default arguments are depreciated, use delegation if you must

~/myprog/foo.hpp                           ~/myprog/foo.cpp
namespace bar {                            #include <iostream>
  class Foo {                              #include "foo.hpp"
  public:
     explicit Foo(int seed);               namespace {
     void calc(int number = 7);              int myMagic(int a, int b) {
     int value() const;                        return a + b - 3 + 8 - 5;
     void print(char* prefix) const;         }
  private:                                 }
     int value_;
  };                                       namespace bar {
}                                            Foo::Foo(int seed) : value_(seed) {
                                             }

                                               void Foo::calc(int number) {
                                                 value_ += myMagic(value_, number);
                                               }

~/myprog/main.cpp                              int Foo::value() const {
                                                 return value_;
#include "foo.hpp"                             }
int main() {                                   void Foo::print(char *prefix) const {
  bar::Foo foo(2);                               std::cout << prefix << value_ << "n";
  char * prefix = "the answer=";               }
  for(int i=0; i<4; i++) {                 }
    foo.calc(i);
  }
  foo.print(prefix);
  return 0;
}
17. default arguments are depreciated, use delegation if you must

~/myprog/foo.hpp                           ~/myprog/foo.cpp
namespace bar {                            #include <iostream>
  class Foo {                              #include "foo.hpp"
  public:
     explicit Foo(int seed);               namespace {
     void calc(int number);                  int myMagic(int a, int b) {
     int value() const;                        return a + b - 3 + 8 - 5;
     void print(char* prefix) const;         }
  private:                                 }
     int value_;
  };                                       namespace bar {
}                                            Foo::Foo(int seed) : value_(seed) {
                                             }

                                               void Foo::calc(int number) {
                                                 value_ += myMagic(value_, number);
                                               }

~/myprog/main.cpp                              int Foo::value() const {
                                                 return value_;
#include "foo.hpp"                             }
int main() {                                   void Foo::print(char *prefix) const {
  bar::Foo foo(2);                               std::cout << prefix << value_ << "n";
  char * prefix = "the answer=";               }
  for(int i=0; i<4; i++) {                 }
    foo.calc(i);
  }
  foo.print(prefix);
  return 0;
}
18. the K&R vs BS war is over, use an extra space around & and *

~/myprog/foo.hpp                          ~/myprog/foo.cpp
namespace bar {                           #include <iostream>
  class Foo {                             #include "foo.hpp"
  public:
     explicit Foo(int seed);              namespace {
     void calc(int number);                 int myMagic(int a, int b) {
     int value() const;                       return a + b - 3 + 8 - 5;
     void print(char* prefix) const;        }
  private:                                }
     int value_;
  };                                      namespace bar {
}                                           Foo::Foo(int seed) : value_(seed) {
                                            }

                                              void Foo::calc(int number) {
                                                value_ += myMagic(value_, number);
                                              }

~/myprog/main.cpp                             int Foo::value() const {
                                                return value_;
#include "foo.hpp"                            }
int main() {                                  void Foo::print(char *prefix) const {
  bar::Foo foo(2);                              std::cout << prefix << value_ << "n";
  char * prefix = "the answer=";              }
  for(int i=0; i<4; i++) {                }
    foo.calc(i);
  }
  foo.print(prefix);
  return 0;
}
18. the K&R vs BS war is over, use an extra space around & and *

~/myprog/foo.hpp                          ~/myprog/foo.cpp
namespace bar {                           #include <iostream>
  class Foo {                             #include "foo.hpp"
  public:
     explicit Foo(int seed);              namespace {
     void calc(int number);                 int myMagic(int a, int b) {
     int value() const;                       return a + b - 3 + 8 - 5;
     void print(char * prefix) const;       }
  private:                                }
     int value_;
  };                                      namespace bar {
}                                           Foo::Foo(int seed) : value_(seed) {
                                            }

                                              void Foo::calc(int number) {
                                                value_ += myMagic(value_, number);
                                              }

~/myprog/main.cpp                             int Foo::value() const {
                                                return value_;
#include "foo.hpp"                            }
int main() {                                  void Foo::print(char * prefix) const {
  bar::Foo foo(2);                              std::cout << prefix << value_ << "n";
  char * prefix = "the answer=";              }
  for(int i=0; i<4; i++) {                }
    foo.calc(i);
  }
  foo.print(prefix);
  return 0;
}
19. by not specifying const you say that something will change

~/myprog/foo.hpp                           ~/myprog/foo.cpp
namespace bar {                            #include <iostream>
  class Foo {                              #include "foo.hpp"
  public:
     explicit Foo(int seed);               namespace {
     void calc(int number);                  int myMagic(int a, int b) {
     int value() const;                        return a + b - 3 + 8 - 5;
     void print(char * prefix) const;        }
  private:                                 }
     int value_;
  };                                       namespace bar {
}                                            Foo::Foo(int seed) : value_(seed) {
                                             }

                                               void Foo::calc(int number) {
                                                 value_ += myMagic(value_, number);
                                               }

~/myprog/main.cpp                              int Foo::value() const {
                                                 return value_;
#include "foo.hpp"                             }
int main() {                                   void Foo::print(char * prefix) const {
  bar::Foo foo(2);                               std::cout << prefix << value_ << "n";
  char * prefix = "the answer=";               }
  for(int i=0; i<4; i++) {                 }
    foo.calc(i);
  }
  foo.print(prefix);
  return 0;
}
19. by not specifying const you say that something will change

~/myprog/foo.hpp                              ~/myprog/foo.cpp
namespace bar {                               #include <iostream>
  class Foo {                                 #include "foo.hpp"
  public:
     explicit Foo(int seed);                  namespace {
     void calc(int number);                     int myMagic(int a, int b) {
     int value() const;                           return a + b - 3 + 8 - 5;
     void print(const char * prefix) const;     }
  private:                                    }
     int value_;
  };                                          namespace bar {
}                                               Foo::Foo(int seed) : value_(seed) {
                                                }

                                                  void Foo::calc(int number) {
                                                    value_ += myMagic(value_, number);
                                                  }

~/myprog/main.cpp                                 int Foo::value() const {
                                                    return value_;
#include "foo.hpp"                                }
int main() {                                      void Foo::print(const char * prefix) const {
  bar::Foo foo(2);                                  std::cout << prefix << value_ << "n";
  const char * prefix = "the answer=";            }
  for(int i=0; i<4; i++) {                    }
    foo.calc(i);
  }
  foo.print(prefix);
  return 0;
}
20. reduce scope of variables

~/myprog/foo.hpp                              ~/myprog/foo.cpp
namespace bar {                               #include <iostream>
  class Foo {                                 #include "foo.hpp"
  public:
     explicit Foo(int seed);                  namespace {
     void calc(int number);                     int myMagic(int a, int b) {
     int value() const;                           return a + b - 3 + 8 - 5;
     void print(const char * prefix) const;     }
  private:                                    }
     int value_;
  };                                          namespace bar {
}                                               Foo::Foo(int seed) : value_(seed) {
                                                }

                                                  void Foo::calc(int number) {
                                                    value_ += myMagic(value_, number);
                                                  }

~/myprog/main.cpp                                 int Foo::value() const {
                                                    return value_;
#include "foo.hpp"                                }
int main() {                                      void Foo::print(const char * prefix) const {
  bar::Foo foo(2);                                  std::cout << prefix << value_ << "n";
  const char * prefix = "the answer=";            }
  for(int i=0; i<4; i++) {                    }
    foo.calc(i);
  }
  foo.print(prefix);
  return 0;
}
20. reduce scope of variables

~/myprog/foo.hpp                              ~/myprog/foo.cpp
namespace bar {                               #include <iostream>
  class Foo {                                 #include "foo.hpp"
  public:
     explicit Foo(int seed);                  namespace {
     void calc(int number);                     int myMagic(int a, int b) {
     int value() const;                           return a + b - 3 + 8 - 5;
     void print(const char * prefix) const;     }
  private:                                    }
     int value_;
  };                                          namespace bar {
}                                               Foo::Foo(int seed) : value_(seed) {
                                                }

                                                  void Foo::calc(int number) {
                                                    value_ += myMagic(value_, number);
                                                  }

~/myprog/main.cpp                                 int Foo::value() const {
                                                    return value_;
#include "foo.hpp"                                }
int main() {                                      void Foo::print(const char * prefix) const {
  bar::Foo foo(2);                                  std::cout << prefix << value_ << "n";
  for(int i=0; i<4; i++) {                        }
    foo.calc(i);                              }
  }
  const char * prefix = "the answer=";
  foo.print(prefix);
  return 0;
}
21. for-loops in C++ are often not written like this

~/myprog/foo.hpp                               ~/myprog/foo.cpp
namespace bar {                                #include <iostream>
  class Foo {                                  #include "foo.hpp"
  public:
     explicit Foo(int seed);                   namespace {
     void calc(int number);                      int myMagic(int a, int b) {
     int value() const;                            return a + b - 3 + 8 - 5;
     void print(const char * prefix) const;      }
  private:                                     }
     int value_;
  };                                           namespace bar {
}                                                Foo::Foo(int seed) : value_(seed) {
                                                 }

                                                   void Foo::calc(int number) {
                                                     value_ += myMagic(value_, number);
                                                   }

~/myprog/main.cpp                                  int Foo::value() const {
                                                     return value_;
#include "foo.hpp"                                 }
int main() {                                       void Foo::print(const char * prefix) const {
  bar::Foo foo(2);                                   std::cout << prefix << value_ << "n";
  for(int i=0; i<4; i++) {                         }
    foo.calc(i);                               }
  }
  const char * prefix = "the answer=";
  foo.print(prefix);
  return 0;
}
21. for-loops in C++ are often not written like this

~/myprog/foo.hpp                               ~/myprog/foo.cpp
namespace bar {                                #include <iostream>
  class Foo {                                  #include "foo.hpp"
  public:
     explicit Foo(int seed);                   namespace {
     void calc(int number);                      int myMagic(int a, int b) {
     int value() const;                            return a + b - 3 + 8 - 5;
     void print(const char * prefix) const;      }
  private:                                     }
     int value_;
  };                                           namespace bar {
}                                                Foo::Foo(int seed) : value_(seed) {
                                                 }

                                                   void Foo::calc(int number) {
                                                     value_ += myMagic(value_, number);
                                                   }

~/myprog/main.cpp                                  int Foo::value() const {
                                                     return value_;
#include "foo.hpp"                                 }
int main() {                                       void Foo::print(const char * prefix) const {
  bar::Foo foo(2);                                   std::cout << prefix << value_ << "n";
  for (int i = 0; i != 4; ++i) {                   }
    foo.calc(i);                               }
  }
  const char * prefix = "the answer=";
  foo.print(prefix);
  return 0;
}
22. in C++ you do not need to explicitly return from main

~/myprog/foo.hpp                              ~/myprog/foo.cpp
namespace bar {                               #include <iostream>
  class Foo {                                 #include "foo.hpp"
  public:
     explicit Foo(int seed);                  namespace {
     void calc(int number);                     int myMagic(int a, int b) {
     int value() const;                           return a + b - 3 + 8 - 5;
     void print(const char * prefix) const;     }
  private:                                    }
     int value_;
  };                                          namespace bar {
}                                               Foo::Foo(int seed) : value_(seed) {
                                                }

                                                  void Foo::calc(int number) {
                                                    value_ += myMagic(value_, number);
                                                  }

~/myprog/main.cpp                                 int Foo::value() const {
                                                    return value_;
#include "foo.hpp"                                }
int main() {                                      void Foo::print(const char * prefix) const {
  bar::Foo foo(2);                                  std::cout << prefix << value_ << "n";
  for (int i = 0; i != 4; ++i) {                  }
    foo.calc(i);                              }
  }
  const char * prefix = "the answer=";
  foo.print(prefix);
  return 0;
}
22. in C++ you do not need to explicitly return from main

~/myprog/foo.hpp                              ~/myprog/foo.cpp
namespace bar {                               #include <iostream>
  class Foo {                                 #include "foo.hpp"
  public:
     explicit Foo(int seed);                  namespace {
     void calc(int number);                     int myMagic(int a, int b) {
     int value() const;                           return a + b - 3 + 8 - 5;
     void print(const char * prefix) const;     }
  private:                                    }
     int value_;
  };                                          namespace bar {
}                                               Foo::Foo(int seed) : value_(seed) {
                                                }

                                                  void Foo::calc(int number) {
                                                    value_ += myMagic(value_, number);
                                                  }

~/myprog/main.cpp                                 int Foo::value() const {
                                                    return value_;
#include "foo.hpp"                                }
int main() {                                      void Foo::print(const char * prefix) const {
  bar::Foo foo(2);                                  std::cout << prefix << value_ << "n";
  for (int i = 0; i != 4; ++i) {                  }
    foo.calc(i);                              }
  }
  const char * prefix = "the answer=";
  foo.print(prefix);
  return 0;
}
22. in C++ you do not need to explicitly return from main

~/myprog/foo.hpp                              ~/myprog/foo.cpp
namespace bar {                               #include <iostream>
  class Foo {                                 #include "foo.hpp"
  public:
     explicit Foo(int seed);                  namespace {
     void calc(int number);                     int myMagic(int a, int b) {
     int value() const;                           return a + b - 3 + 8 - 5;
     void print(const char * prefix) const;     }
  private:                                    }
     int value_;
  };                                          namespace bar {
}                                               Foo::Foo(int seed) : value_(seed) {
                                                }

                                                  void Foo::calc(int number) {
                                                    value_ += myMagic(value_, number);
                                                  }

~/myprog/main.cpp                                 int Foo::value() const {
                                                    return value_;
#include "foo.hpp"                                }
int main() {                                      void Foo::print(const char * prefix) const {
  bar::Foo foo(2);                                  std::cout << prefix << value_ << "n";
  for (int i = 0; i != 4; ++i) {                  }
    foo.calc(i);                              }
  }
  const char * prefix = "the answer=";
  foo.print(prefix);
}
23. inject side-effects if you must have them

~/myprog/foo.hpp                                ~/myprog/foo.cpp
namespace bar {                                 #include <iostream>
  class Foo {                                   #include "foo.hpp"
  public:
     explicit Foo(int seed);                    namespace {
     void calc(int number);                       int myMagic(int a, int b) {
     int value() const;                             return a + b - 3 + 8 - 5;
     void print(const char * prefix) const;       }
  private:                                      }
     int value_;
  };                                            namespace bar {
}                                                 Foo::Foo(int seed) : value_(seed) {
                                                  }

                                                    void Foo::calc(int number) {
                                                      value_ += myMagic(value_, number);
                                                    }

~/myprog/main.cpp                                   int Foo::value() const {
                                                      return value_;
#include "foo.hpp"                                  }
int main() {                                        void Foo::print(const char * prefix) const {
  bar::Foo foo(2);                                    std::cout << prefix << value_ << "n";
  for (int i = 0; i != 4; ++i) {                    }
    foo.calc(i);                                }
  }
  const char * prefix = "the answer=";
  foo.print(prefix);
}
23. inject side-effects if you must have them

~/myprog/foo.hpp                                ~/myprog/foo.cpp
namespace bar {                                 #include <ostream>
  class Foo {                                   #include "foo.hpp"
  public:
     explicit Foo(int seed);                    namespace {
     void calc(int number);                       int myMagic(int a, int b) {
     int value() const;                             return a + b - 3 + 8 - 5;
     void print(std::ostream & out,               }
                 const char * prefix) const;    }
  private:
     int value_;                                namespace bar {
  };                                              Foo::Foo(int seed) : value_(seed) {
}                                                 }

                                                    void Foo::calc(int number) {
                                                      value_ += myMagic(value_, number);
                                                    }

~/myprog/main.cpp                                   int Foo::value() const {
                                                      return value_;
#include <iostream>                                 }
#include "foo.hpp"
                                                    void Foo::print(std::ostream & out,
int main() {                                                        const char * prefix) const {
  bar::Foo foo(2);                                    out << prefix << value_ << "n";
  for (int i = 0; i != 4; ++i) {                    }
    foo.calc(i);                                }
  }
  const char * prefix = "the answer=";
  foo.print(std::cout, prefix);
}
24. make sure headers compile by itself

~/myprog/foo.hpp                               ~/myprog/foo.cpp
namespace bar {                                #include <ostream>
  class Foo {                                  #include "foo.hpp"
  public:
     explicit Foo(int seed);                   namespace {
     void calc(int number);                      int myMagic(int a, int b) {
     int value() const;                            return a + b - 3 + 8 - 5;
     void print(std::ostream & out,              }
                 const char * prefix) const;   }
  private:
     int value_;                               namespace bar {
  };                                             Foo::Foo(int seed) : value_(seed) {
}                                                }

                                                   void Foo::calc(int number) {
                                                     value_ += myMagic(value_, number);
                                                   }

~/myprog/main.cpp                                  int Foo::value() const {
                                                     return value_;
#include <iostream>                                }
#include "foo.hpp"
                                                   void Foo::print(std::ostream & out,
int main() {                                                       const char * prefix) const {
  bar::Foo foo(2);                                   out << prefix << value_ << "n";
  for (int i = 0; i != 4; ++i) {                   }
    foo.calc(i);                               }
  }
  const char * prefix = "the answer=";
  foo.print(std::cout, prefix);
}
24. make sure headers compile by itself

~/myprog/foo.hpp                               ~/myprog/foo.cpp
#include <iostream>                            #include <ostream>
                                               #include "foo.hpp"
namespace bar {
  class Foo {                                  namespace {
  public:                                        int myMagic(int a, int b) {
     explicit Foo(int seed);                       return a + b - 3 + 8 - 5;
     void calc(int number);                      }
     int value() const;                        }
     void print(std::ostream & out,
                 const char * prefix) const;   namespace bar {
  private:                                       Foo::Foo(int seed) : value_(seed) {
     int value_;                                 }
  };
}                                                  void Foo::calc(int number) {
                                                     value_ += myMagic(value_, number);
                                                   }

~/myprog/main.cpp                                  int Foo::value() const {
                                                     return value_;
#include <iostream>                                }
#include "foo.hpp"
                                                   void Foo::print(std::ostream & out,
int main() {                                                       const char * prefix) const {
  bar::Foo foo(2);                                   out << prefix << value_ << "n";
  for (int i = 0; i != 4; ++i) {                   }
    foo.calc(i);                               }
  }
  const char * prefix = "the answer=";
  foo.print(std::cout, prefix);
}
25. include your own header file first, standard libraries last

~/myprog/foo.hpp                               ~/myprog/foo.cpp
#include <iostream>                            #include <ostream>
                                               #include "foo.hpp"
namespace bar {
  class Foo {                                  namespace {
  public:                                        int myMagic(int a, int b) {
     explicit Foo(int seed);                       return a + b - 3 + 8 - 5;
     void calc(int number);                      }
     int value() const;                        }
     void print(std::ostream & out,
                 const char * prefix) const;   namespace bar {
  private:                                       Foo::Foo(int seed) : value_(seed) {
     int value_;                                 }
  };
}                                                  void Foo::calc(int number) {
                                                     value_ += myMagic(value_, number);
                                                   }

~/myprog/main.cpp                                  int Foo::value() const {
                                                     return value_;
#include <iostream>                                }
#include "foo.hpp"
                                                   void Foo::print(std::ostream & out,
int main() {                                                       const char * prefix) const {
  bar::Foo foo(2);                                   out << prefix << value_ << "n";
  for (int i = 0; i != 4; ++i) {                   }
    foo.calc(i);                               }
  }
  const char * prefix = "the answer=";
  foo.print(std::cout, prefix);
}
25. include your own header file first, standard libraries last

~/myprog/foo.hpp                               ~/myprog/foo.cpp
#include <iostream>                            #include "foo.hpp"
                                               #include <ostream>
namespace bar {
  class Foo {                                  namespace {
  public:                                        int myMagic(int a, int b) {
     explicit Foo(int seed);                       return a + b - 3 + 8 - 5;
     void calc(int number);                      }
     int value() const;                        }
     void print(std::ostream & out,
                 const char * prefix) const;   namespace bar {
  private:                                       Foo::Foo(int seed) : value_(seed) {
     int value_;                                 }
  };
}                                                  void Foo::calc(int number) {
                                                     value_ += myMagic(value_, number);
                                                   }

~/myprog/main.cpp                                  int Foo::value() const {
                                                     return value_;
#include "foo.hpp"                                 }
#include <iostream>
                                                   void Foo::print(std::ostream & out,
int main() {                                                       const char * prefix) const {
  bar::Foo foo(2);                                   out << prefix << value_ << "n";
  for (int i = 0; i != 4; ++i) {                   }
    foo.calc(i);                               }
  }
  const char * prefix = "the answer=";
  foo.print(std::cout, prefix);
}
26. prefer forward declarations in header files

~/myprog/foo.hpp                               ~/myprog/foo.cpp
#include <iostream>                            #include "foo.hpp"
                                               #include <ostream>
namespace bar {
  class Foo {                                  namespace {
  public:                                        int myMagic(int a, int b) {
     explicit Foo(int seed);                       return a + b - 3 + 8 - 5;
     void calc(int number);                      }
     int value() const;                        }
     void print(std::ostream & out,
                 const char * prefix) const;   namespace bar {
  private:                                       Foo::Foo(int seed) : value_(seed) {
     int value_;                                 }
  };
}                                                  void Foo::calc(int number) {
                                                     value_ += myMagic(value_, number);
                                                   }

~/myprog/main.cpp                                  int Foo::value() const {
                                                     return value_;
#include "foo.hpp"                                 }
#include <iostream>
                                                   void Foo::print(std::ostream & out,
int main() {                                                       const char * prefix) const {
  bar::Foo foo(2);                                   out << prefix << value_ << "n";
  for (int i = 0; i != 4; ++i) {                   }
    foo.calc(i);                               }
  }
  const char * prefix = "the answer=";
  foo.print(std::cout, prefix);
}
26. prefer forward declarations in header files

~/myprog/foo.hpp                               ~/myprog/foo.cpp
#include <iosfwd>                              #include "foo.hpp"
                                               #include <ostream>
namespace bar {
  class Foo {                                  namespace {
  public:                                        int myMagic(int a, int b) {
     explicit Foo(int seed);                       return a + b - 3 + 8 - 5;
     void calc(int number);                      }
     int value() const;                        }
     void print(std::ostream & out,
                 const char * prefix) const;   namespace bar {
  private:                                       Foo::Foo(int seed) : value_(seed) {
     int value_;                                 }
  };
}                                                  void Foo::calc(int number) {
                                                     value_ += myMagic(value_, number);
                                                   }

~/myprog/main.cpp                                  int Foo::value() const {
                                                     return value_;
#include "foo.hpp"                                 }
#include <iostream>
                                                   void Foo::print(std::ostream & out,
int main() {                                                       const char * prefix) const {
  bar::Foo foo(2);                                   out << prefix << value_ << "n";
  for (int i = 0; i != 4; ++i) {                   }
    foo.calc(i);                               }
  }
  const char * prefix = "the answer=";
  foo.print(std::cout, prefix);
}
27. don't need braces here

~/myprog/foo.hpp                               ~/myprog/foo.cpp
#include <iosfwd>                              #include "foo.hpp"
                                               #include <ostream>
namespace bar {
  class Foo {                                  namespace {
  public:                                        int myMagic(int a, int b) {
     explicit Foo(int seed);                       return a + b - 3 + 8 - 5;
     void calc(int number);                      }
     int value() const;                        }
     void print(std::ostream & out,
                 const char * prefix) const;   namespace bar {
  private:                                       Foo::Foo(int seed) : value_(seed) {
     int value_;                                 }
  };
}                                                  void Foo::calc(int number) {
                                                     value_ += myMagic(value_, number);
                                                   }

~/myprog/main.cpp                                  int Foo::value() const {
                                                     return value_;
#include "foo.hpp"                                 }
#include <iostream>
                                                   void Foo::print(std::ostream & out,
int main() {                                                       const char * prefix) const {
  bar::Foo foo(2);                                   out << prefix << value_ << "n";
  for (int i = 0; i != 4; ++i) {                   }
    foo.calc(i);                               }
  }
  const char * prefix = "the answer=";
  foo.print(std::cout, prefix);
}
27. don't need braces here

~/myprog/foo.hpp                               ~/myprog/foo.cpp
#include <iosfwd>                              #include "foo.hpp"
                                               #include <ostream>
namespace bar {
  class Foo {                                  namespace {
  public:                                        int myMagic(int a, int b) {
     explicit Foo(int seed);                       return a + b - 3 + 8 - 5;
     void calc(int number);                      }
     int value() const;                        }
     void print(std::ostream & out,
                 const char * prefix) const;   namespace bar {
  private:                                       Foo::Foo(int seed) : value_(seed) {
     int value_;                                 }
  };
}                                                  void Foo::calc(int number) {
                                                     value_ += myMagic(value_, number);
                                                   }

~/myprog/main.cpp                                  int Foo::value() const {
                                                     return value_;
#include "foo.hpp"                                 }
#include <iostream>
                                                   void Foo::print(std::ostream & out,
int main() {                                                       const char * prefix) const {
  bar::Foo foo(2);                                   out << prefix << value_ << "n";
  for (int i = 0; i != 4; ++i)                     }
    foo.calc(i);                               }
  const char * prefix = "the answer=";
  foo.print(std::cout, prefix);
}
28. avoid side-effects if you can, prefer free-standing functions

~/myprog/foo.hpp                               ~/myprog/foo.cpp
#include <iosfwd>                              #include "foo.hpp"
                                               #include <ostream>
namespace bar {
  class Foo {                                  namespace {
  public:                                        int myMagic(int a, int b) {
     explicit Foo(int seed);                       return a + b - 3 + 8 - 5;
     void calc(int number);                      }
     int value() const;                        }
     void print(std::ostream & out,
                 const char * prefix) const;   namespace bar {
  private:                                       Foo::Foo(int seed) : value_(seed) {
     int value_;                                 }
  };
}                                                  void Foo::calc(int number) {
                                                     value_ += myMagic(value_, number);
                                                   }

~/myprog/main.cpp                                  int Foo::value() const {
                                                     return value_;
#include "foo.hpp"                                 }
#include <iostream>
                                                   void Foo::print(std::ostream & out,
int main() {                                                       const char * prefix) const {
  bar::Foo foo(2);                                   out << prefix << value_ << "n";
  for (int i = 0; i != 4; ++i)                     }
    foo.calc(i);                               }
  const char * prefix = "the answer=";
  foo.print(std::cout, prefix);
}
28. avoid side-effects if you can, prefer free-standing functions

~/myprog/foo.hpp                             ~/myprog/foo.cpp
#include <iosfwd>                            #include "foo.hpp"
                                             #include <ostream>
namespace bar {
  class Foo {                                namespace {
  public:                                      int myMagic(int a, int b) {
     explicit Foo(int seed);                     return a + b - 3 + 8 - 5;
     void calc(int number);                    }
     int value() const;                      }
  private:
     int value_;                             namespace bar {
  };                                           Foo::Foo(int seed) : value_(seed) {
  void print(std::ostream & out,               }
              const char * prefix,
              const Foo & foo);                  void Foo::calc(int number) {
}                                                  value_ += myMagic(value_, number);
                                                 }

~/myprog/main.cpp                                int Foo::value() const {
                                                   return value_;
#include "foo.hpp"                               }
#include <iostream>
                                                 void print(std::ostream & out,
int main() {                                                const char * prefix,
  bar::Foo foo(2);                                          const Foo & foo) {
  for (int i = 0; i != 4; ++i)                     out << prefix << foo.value() << "n";
    foo.calc(i);                                 }
  const char * prefix = "the answer=";       }
  print(std::cout, prefix, foo);
}
29. do not open a namespace when implementing free-standing functions

~/myprog/foo.hpp                         ~/myprog/foo.cpp
#include <iosfwd>                        #include "foo.hpp"
                                         #include <ostream>
namespace bar {
  class Foo {                            namespace {
  public:                                  int myMagic(int a, int b) {
     explicit Foo(int seed);                 return a + b - 3 + 8 - 5;
     void calc(int number);                }
     int value() const;                  }
  private:
     int value_;                         namespace bar {
  };                                       Foo::Foo(int seed) : value_(seed) {
  void print(std::ostream & out,           }
              const char * prefix,
              const Foo & foo);              void Foo::calc(int number) {
}                                              value_ += myMagic(value_, number);
                                             }

~/myprog/main.cpp                            int Foo::value() const {
                                               return value_;
#include "foo.hpp"                           }
#include <iostream>
                                             void print(std::ostream & out,
int main() {                                            const char * prefix,
  bar::Foo foo(2);                                      const Foo & foo) {
  for (int i = 0; i != 4; ++i)                 out << prefix << foo.value() << "n";
    foo.calc(i);                             }
  const char * prefix = "the answer=";   }
  print(std::cout, prefix, foo);
}
29. do not open a namespace when implementing free-standing functions

~/myprog/foo.hpp                         ~/myprog/foo.cpp
#include <iosfwd>                        #include "foo.hpp"
                                         #include <ostream>
namespace bar {
  class Foo {                            namespace {
  public:                                  int myMagic(int a, int b) {
     explicit Foo(int seed);                 return a + b - 3 + 8 - 5;
     void calc(int number);                }
     int value() const;                  }
  private:
     int value_;                         namespace bar {
  };                                       Foo::Foo(int seed) : value_(seed) {
  void print(std::ostream & out,           }
              const char * prefix,
              const Foo & foo);              void Foo::calc(int number) {
}                                              value_ += myMagic(value_, number);
                                             }

~/myprog/main.cpp                            int Foo::value() const {
                                               return value_;
#include "foo.hpp"                           }
#include <iostream>                      }
int main() {                             void bar::print(std::ostream & out,
  bar::Foo foo(2);                                       const char * prefix,
  for (int i = 0; i != 4; ++i)                           const bar::Foo & foo) {
    foo.calc(i);                           out << prefix << foo.value() << "n";
  const char * prefix = "the answer=";   }
  print(std::cout, prefix, foo);
}
30. operator overloading is sometimes a nice thing

~/myprog/foo.hpp                           ~/myprog/foo.cpp
#include <iosfwd>                          #include "foo.hpp"
                                           #include <ostream>
namespace bar {
  class Foo {                              namespace {
  public:                                    int myMagic(int a, int b) {
     explicit Foo(int seed);                   return a + b - 3 + 8 - 5;
     void calc(int number);                  }
     int value() const;                    }
  private:
     int value_;                           namespace bar {
  };                                         Foo::Foo(int seed) : value_(seed) {
  void print(std::ostream & out,             }
              const char * prefix,
              const Foo & foo);                void Foo::calc(int number) {
}                                                value_ += myMagic(value_, number);
                                               }

~/myprog/main.cpp                              int Foo::value() const {
                                                 return value_;
#include "foo.hpp"                             }
#include <iostream>                        }
int main() {                               void bar::print(std::ostream & out,
  bar::Foo foo(2);                                         const char * prefix,
  for (int i = 0; i != 4; ++i)                             const bar::Foo & foo) {
    foo.calc(i);                             out << prefix << foo.value() << "n";
  const char * prefix = "the answer=";     }
  print(std::cout, prefix, foo);
}
C++ idioms by example (Nov 2008)
C++ idioms by example (Nov 2008)
C++ idioms by example (Nov 2008)
C++ idioms by example (Nov 2008)
C++ idioms by example (Nov 2008)
C++ idioms by example (Nov 2008)
C++ idioms by example (Nov 2008)
C++ idioms by example (Nov 2008)
C++ idioms by example (Nov 2008)
C++ idioms by example (Nov 2008)
C++ idioms by example (Nov 2008)

More Related Content

What's hot

The Microkernel Mach Under NeXTSTEP
The Microkernel Mach Under NeXTSTEPThe Microkernel Mach Under NeXTSTEP
The Microkernel Mach Under NeXTSTEP
Gregor Schmidt
 

What's hot (20)

Fun with Lambdas: C++14 Style (part 1)
Fun with Lambdas: C++14 Style (part 1)Fun with Lambdas: C++14 Style (part 1)
Fun with Lambdas: C++14 Style (part 1)
 
C++11
C++11C++11
C++11
 
Q2.12: Debugging with GDB
Q2.12: Debugging with GDBQ2.12: Debugging with GDB
Q2.12: Debugging with GDB
 
How A Compiler Works: GNU Toolchain
How A Compiler Works: GNU ToolchainHow A Compiler Works: GNU Toolchain
How A Compiler Works: GNU Toolchain
 
OOP in C++
OOP in C++OOP in C++
OOP in C++
 
The Internals of "Hello World" Program
The Internals of "Hello World" ProgramThe Internals of "Hello World" Program
The Internals of "Hello World" Program
 
An introduction to Rust: the modern programming language to develop safe and ...
An introduction to Rust: the modern programming language to develop safe and ...An introduction to Rust: the modern programming language to develop safe and ...
An introduction to Rust: the modern programming language to develop safe and ...
 
GDB Rocks!
GDB Rocks!GDB Rocks!
GDB Rocks!
 
The Microkernel Mach Under NeXTSTEP
The Microkernel Mach Under NeXTSTEPThe Microkernel Mach Under NeXTSTEP
The Microkernel Mach Under NeXTSTEP
 
Preprocessors
Preprocessors Preprocessors
Preprocessors
 
Virtual Machine Constructions for Dummies
Virtual Machine Constructions for DummiesVirtual Machine Constructions for Dummies
Virtual Machine Constructions for Dummies
 
TMUX Rocks!
TMUX Rocks!TMUX Rocks!
TMUX Rocks!
 
Learn C Programming Language by Using GDB
Learn C Programming Language by Using GDBLearn C Programming Language by Using GDB
Learn C Programming Language by Using GDB
 
TDD in C - Recently Used List Kata
TDD in C - Recently Used List KataTDD in C - Recently Used List Kata
TDD in C - Recently Used List Kata
 
C++ programming function
C++ programming functionC++ programming function
C++ programming function
 
C++ Programming Course
C++ Programming CourseC++ Programming Course
C++ Programming Course
 
OPcacheの新機能ファイルベースキャッシュの内部実装を読んでみた
OPcacheの新機能ファイルベースキャッシュの内部実装を読んでみたOPcacheの新機能ファイルベースキャッシュの内部実装を読んでみた
OPcacheの新機能ファイルベースキャッシュの内部実装を読んでみた
 
Deep drive into rust programming language
Deep drive into rust programming languageDeep drive into rust programming language
Deep drive into rust programming language
 
Modern C++ Explained: Move Semantics (Feb 2018)
Modern C++ Explained: Move Semantics (Feb 2018)Modern C++ Explained: Move Semantics (Feb 2018)
Modern C++ Explained: Move Semantics (Feb 2018)
 
Algorithmique programmation2018
Algorithmique programmation2018Algorithmique programmation2018
Algorithmique programmation2018
 

Viewers also liked

Viewers also liked (20)

Deep C
Deep CDeep C
Deep C
 
Intro. to prog. c++
Intro. to prog. c++Intro. to prog. c++
Intro. to prog. c++
 
Singleton is not_the_only_pattern
Singleton is not_the_only_patternSingleton is not_the_only_pattern
Singleton is not_the_only_pattern
 
Esoft Metro Campus - Programming with C++
Esoft Metro Campus - Programming with C++Esoft Metro Campus - Programming with C++
Esoft Metro Campus - Programming with C++
 
C++ Programming Language
C++ Programming Language C++ Programming Language
C++ Programming Language
 
Penerjemahan idiom
Penerjemahan idiomPenerjemahan idiom
Penerjemahan idiom
 
iOS 6 Exploitation 280 days later
iOS 6 Exploitation 280 days lateriOS 6 Exploitation 280 days later
iOS 6 Exploitation 280 days later
 
Dconf2015 d2 t4
Dconf2015 d2 t4Dconf2015 d2 t4
Dconf2015 d2 t4
 
Linked lists
Linked listsLinked lists
Linked lists
 
Data mining
Data miningData mining
Data mining
 
C Standards: main()
C Standards: main()C Standards: main()
C Standards: main()
 
Functional Leap of Faith (Keynote at JDay Lviv 2014)
Functional Leap of Faith (Keynote at JDay Lviv 2014)Functional Leap of Faith (Keynote at JDay Lviv 2014)
Functional Leap of Faith (Keynote at JDay Lviv 2014)
 
C++ TUTORIAL 8
C++ TUTORIAL 8C++ TUTORIAL 8
C++ TUTORIAL 8
 
What Can Compilers Do for Us?
What Can Compilers Do for Us?What Can Compilers Do for Us?
What Can Compilers Do for Us?
 
Operators in C Programming
Operators in C ProgrammingOperators in C Programming
Operators in C Programming
 
Three Optimization Tips for C++
Three Optimization Tips for C++Three Optimization Tips for C++
Three Optimization Tips for C++
 
Data structures & algorithms lecture 3
Data structures & algorithms lecture 3Data structures & algorithms lecture 3
Data structures & algorithms lecture 3
 
Escape sequence in c part 1
Escape sequence in c   part 1Escape sequence in c   part 1
Escape sequence in c part 1
 
Three Optimization Tips for C++
Three Optimization Tips for C++Three Optimization Tips for C++
Three Optimization Tips for C++
 
358 33 powerpoint-slides_8-linked-lists_chapter-8
358 33 powerpoint-slides_8-linked-lists_chapter-8358 33 powerpoint-slides_8-linked-lists_chapter-8
358 33 powerpoint-slides_8-linked-lists_chapter-8
 

Similar to C++ idioms by example (Nov 2008)

COSCUP2012: How to write a bash script like the python?
COSCUP2012: How to write a bash script like the python?COSCUP2012: How to write a bash script like the python?
COSCUP2012: How to write a bash script like the python?
Lloyd Huang
 
ฟังก์ชั่นย่อยและโปรแกรมมาตรฐาน ม. 6 1
ฟังก์ชั่นย่อยและโปรแกรมมาตรฐาน ม. 6  1ฟังก์ชั่นย่อยและโปรแกรมมาตรฐาน ม. 6  1
ฟังก์ชั่นย่อยและโปรแกรมมาตรฐาน ม. 6 1
Little Tukta Lita
 
C ISRO Debugging
C ISRO DebuggingC ISRO Debugging
C ISRO Debugging
splix757
 
Cbse question-paper-computer-science-2009
Cbse question-paper-computer-science-2009Cbse question-paper-computer-science-2009
Cbse question-paper-computer-science-2009
Deepak Singh
 
Computer science-2010-cbse-question-paper
Computer science-2010-cbse-question-paperComputer science-2010-cbse-question-paper
Computer science-2010-cbse-question-paper
Deepak Singh
 

Similar to C++ idioms by example (Nov 2008) (20)

Sbaw091006
Sbaw091006Sbaw091006
Sbaw091006
 
Paradigmas de Linguagens de Programacao - Aula #4
Paradigmas de Linguagens de Programacao - Aula #4Paradigmas de Linguagens de Programacao - Aula #4
Paradigmas de Linguagens de Programacao - Aula #4
 
COSCUP2012: How to write a bash script like the python?
COSCUP2012: How to write a bash script like the python?COSCUP2012: How to write a bash script like the python?
COSCUP2012: How to write a bash script like the python?
 
Go serving: Building server app with go
Go serving: Building server app with goGo serving: Building server app with go
Go serving: Building server app with go
 
ฟังก์ชั่นย่อยและโปรแกรมมาตรฐาน ม. 6 1
ฟังก์ชั่นย่อยและโปรแกรมมาตรฐาน ม. 6  1ฟังก์ชั่นย่อยและโปรแกรมมาตรฐาน ม. 6  1
ฟังก์ชั่นย่อยและโปรแกรมมาตรฐาน ม. 6 1
 
ekb.py - Python VS ...
ekb.py - Python VS ...ekb.py - Python VS ...
ekb.py - Python VS ...
 
Using Flow-based programming to write tools and workflows for Scientific Comp...
Using Flow-based programming to write tools and workflows for Scientific Comp...Using Flow-based programming to write tools and workflows for Scientific Comp...
Using Flow-based programming to write tools and workflows for Scientific Comp...
 
C ISRO Debugging
C ISRO DebuggingC ISRO Debugging
C ISRO Debugging
 
Golang iran - tutorial go programming language - Preliminary
Golang iran - tutorial  go programming language - PreliminaryGolang iran - tutorial  go programming language - Preliminary
Golang iran - tutorial go programming language - Preliminary
 
Cbse question-paper-computer-science-2009
Cbse question-paper-computer-science-2009Cbse question-paper-computer-science-2009
Cbse question-paper-computer-science-2009
 
Function in C program
Function in C programFunction in C program
Function in C program
 
Functions in C
Functions in CFunctions in C
Functions in C
 
Inheritance compiler support
Inheritance compiler supportInheritance compiler support
Inheritance compiler support
 
C++ Chapter IV
C++ Chapter IVC++ Chapter IV
C++ Chapter IV
 
Virtual function
Virtual functionVirtual function
Virtual function
 
Threads and Callbacks for Embedded Python
Threads and Callbacks for Embedded PythonThreads and Callbacks for Embedded Python
Threads and Callbacks for Embedded Python
 
C++aptitude questions and answers
C++aptitude questions and answersC++aptitude questions and answers
C++aptitude questions and answers
 
I need a complete working code for a solution to this problem using .pdf
I need a complete working code for a solution to this problem using .pdfI need a complete working code for a solution to this problem using .pdf
I need a complete working code for a solution to this problem using .pdf
 
Phyton Learning extracts
Phyton Learning extracts Phyton Learning extracts
Phyton Learning extracts
 
Computer science-2010-cbse-question-paper
Computer science-2010-cbse-question-paperComputer science-2010-cbse-question-paper
Computer science-2010-cbse-question-paper
 

Recently uploaded

Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
panagenda
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Safe Software
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Safe Software
 

Recently uploaded (20)

Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
WSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering DevelopersWSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering Developers
 
ICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesICT role in 21st century education and its challenges
ICT role in 21st century education and its challenges
 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistan
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
Exploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusExploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with Milvus
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor Presentation
 
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWEREMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 
Six Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal OntologySix Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal Ontology
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfRising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
 

C++ idioms by example (Nov 2008)

  • 1. C++ Idioms by Example, lesson 1 I Introducing some very basic C++ idioms, rules, guidelines and best practices h a Olve Maudal oma@pvv.org November 2008 Disclaimer: most of the items I will discuss here are indeed idioms and conventions of the C++ language, something that most experts will agree on. However some of the items are based on an ecolect – a programming style that is unique for a limited group of developers. There are also a few items based on my idiolect, which is a programming style that I believe in. And you may argue that one or two things I suggest here are just plain idiotic... My intention is not to tell you how to do C++ programming. I hope to use this presentation as a catalyst for discussion, therefor I have also included some controversial issues. Ignite your flamethrower. Choose your battles!
  • 2. Please criticise this program. ~/myprog/foo.hpp ~/myprog/foo.cpp namespace bar { #include <iostream> class Foo { #include "foo.hpp" int _value; int my_magic(int a, int b); using namespace std; public: Foo(int seed); namespace bar { int calc(int number = 7); Foo::Foo(int seed) { int getValue() { _value = seed; return _value; } } void print(char* prefix); int Foo::my_magic(int a, int b) { }; return a + b - 3 + 8 - 5; } } int Foo::calc(int number) { int result = my_magic(_value, number); _value += result; ~/myprog/main.cpp return result; } #include "foo.hpp" void Foo::print(char *prefix) { int main() { cout << prefix << _value << "n"; bar::Foo foo(2); } char * prefix = "the answer="; } for(int i=0; i<4; i++) { foo.calc(i); Please criticise this program } foo.print(prefix); return 0; } Spend 5-10 minutes to read through the code. Imagine that this is a piece of code that you found in a larger codebase. Criticise everything you see, ... apart from the fact that it is a contrived, incorrect and stupid program that does not do anything useful, and is probably better written in Python as print “the $ cd ~/myprog answer=42” (and do not spend time on the implmentation of my_magic) $ g++ foo.cpp main.cpp && ./a.out the answer=43
  • 3. What do you see in this code? Happiness?
  • 4.
  • 6.
  • 7. I see trouble. It looks like the code has been written by someone with little experience in C++, or even worse, by someone who does not care... Large amount of this kind of code will make your codebase rot. But, once you start to believe - it is time to defeat the deteriorating agents
  • 8.
  • 9. ~/myprog/foo.hpp ~/myprog/foo.cpp namespace bar { #include <iostream> class Foo { #include "foo.hpp" int _value; int my_magic(int a, int b); using namespace std; public: Foo(int seed); namespace bar { int calc(int number = 7); Foo::Foo(int seed) { int getValue() { _value = seed; return _value; } } void print(char* prefix); int Foo::my_magic(int a, int b) { }; return a + b - 3 + 8 - 5; } } int Foo::calc(int number) { int result = my_magic(_value, number); _value += result; ~/myprog/main.cpp return result; } #include "foo.hpp" void Foo::print(char *prefix) { int main() { cout << prefix << _value << "n"; bar::Foo foo(2); } char * prefix = "the answer="; } for(int i=0; i<4; i++) { foo.calc(i); } foo.print(prefix); return 0; } $ cd ~/myprog $ g++ foo.cpp main.cpp && ./a.out the answer=43
  • 10. 1. always compile with high warning level, and treat warnings as errors ~/myprog/foo.hpp ~/myprog/foo.cpp namespace bar { #include <iostream> class Foo { #include "foo.hpp" int _value; int my_magic(int a, int b); using namespace std; public: Foo(int seed); namespace bar { int calc(int number = 7); Foo::Foo(int seed) { int getValue() { _value = seed; return _value; } } void print(char* prefix); int Foo::my_magic(int a, int b) { }; return a + b - 3 + 8 - 5; } } int Foo::calc(int number) { int result = my_magic(_value, number); _value += result; ~/myprog/main.cpp return result; } #include "foo.hpp" void Foo::print(char *prefix) { int main() { cout << prefix << _value << "n"; bar::Foo foo(2); } char * prefix = "the answer="; } for(int i=0; i<4; i++) { foo.calc(i); } foo.print(prefix); return 0; } $ cd ~/myprog $ g++ -Wall -Wextra -pedantic -Werror foo.cpp main.cpp && ./a.out the answer=43
  • 11. 2. always use tools to support the building process ~/myprog/foo.hpp ~/myprog/foo.cpp namespace bar { #include <iostream> class Foo { #include "foo.hpp" int _value; int my_magic(int a, int b); using namespace std; public: Foo(int seed); ~/myprog/Makefile int calc(int number = 7); namespace bar { Foo::Foo(int seed) { int getValue() { _value = seed; return _value; CPPFLAGS=-Wall -Wextra } -pedantic -Werror } LDFLAGS= void print(char* prefix); int Foo::my_magic(int a, int b) { }; return a + b - 3 + 8 - 5; } all: myprog } int Foo::calc(int number) { myprog: foo.o main.o int result = my_magic(_value, number); ~/myprog/main.cpp $(CXX) -o $@ $(LDFLAGS) $+ result; _value += return result; } #include "foo.hpp" clean: void Foo::print(char *prefix) { int main() { rm -f foo.o main.o myprog prefix << _value << cout << "n"; bar::Foo foo(2); } char * prefix = "the answer="; } for(int i=0; i<4; i++) { foo.calc(i); } foo.print(prefix); return 0; } $ cd ~/myprog $ make $ ./myprog the answer=43
  • 12. 3. do not _prefix member variables, use postfix_ if you must ~/myprog/foo.hpp ~/myprog/foo.cpp namespace bar { #include <iostream> class Foo { #include "foo.hpp" int _value; int my_magic(int a, int b); using namespace std; public: Foo(int seed); namespace bar { int calc(int number = 7); Foo::Foo(int seed) { int getValue() { _value = seed; return _value; } } void print(char* prefix); int Foo::my_magic(int a, int b) { }; return a + b - 3 + 8 - 5; } } int Foo::calc(int number) { int result = my_magic(_value, number); _value += result; ~/myprog/main.cpp return result; } #include "foo.hpp" void Foo::print(char *prefix) { int main() { cout << prefix << _value << "n"; bar::Foo foo(2); } char * prefix = "the answer="; } for(int i=0; i<4; i++) { foo.calc(i); } foo.print(prefix); return 0; }
  • 13. 3. do not _prefix member variables, use postfix_ if you must ~/myprog/foo.hpp ~/myprog/foo.cpp namespace bar { #include <iostream> class Foo { #include "foo.hpp" int value_; int my_magic(int a, int b); using namespace std; public: Foo(int seed); namespace bar { int calc(int number = 7); Foo::Foo(int seed) { int getValue() { value_ = seed; return value_; } } void print(char* prefix); int Foo::my_magic(int a, int b) { }; return a + b - 3 + 8 - 5; } } int Foo::calc(int number) { int result = my_magic(value_, number); value_ += result; ~/myprog/main.cpp return result; } #include "foo.hpp" void Foo::print(char *prefix) { int main() { cout << prefix << value_ << "n"; bar::Foo foo(2); } char * prefix = "the answer="; } for(int i=0; i<4; i++) { foo.calc(i); } foo.print(prefix); return 0; }
  • 14. 4. public stuff should be declared first, then the private stuff ~/myprog/foo.hpp ~/myprog/foo.cpp namespace bar { #include <iostream> class Foo { #include "foo.hpp" int value_; int my_magic(int a, int b); using namespace std; public: Foo(int seed); namespace bar { int calc(int number = 7); Foo::Foo(int seed) { int getValue() { value_ = seed; return value_; } } void print(char* prefix); int Foo::my_magic(int a, int b) { }; return a + b - 3 + 8 - 5; } } int Foo::calc(int number) { int result = my_magic(value_, number); value_ += result; ~/myprog/main.cpp return result; } #include "foo.hpp" void Foo::print(char *prefix) { int main() { cout << prefix << value_ << "n"; bar::Foo foo(2); } char * prefix = "the answer="; } for(int i=0; i<4; i++) { foo.calc(i); } foo.print(prefix); return 0; }
  • 15. 4. public stuff should be declared first, then the private stuff ~/myprog/foo.hpp ~/myprog/foo.cpp namespace bar { #include <iostream> class Foo { #include "foo.hpp" public: Foo(int seed); using namespace std; int calc(int number = 7); int getValue() { namespace bar { return value_; Foo::Foo(int seed) { } value_ = seed; void print(char* prefix); } private: int value_; int Foo::my_magic(int a, int b) { int my_magic(int a, int b); return a + b - 3 + 8 - 5; }; } } int Foo::calc(int number) { int result = my_magic(value_, number); value_ += result; ~/myprog/main.cpp return result; } #include "foo.hpp" void Foo::print(char *prefix) { int main() { cout << prefix << value_ << "n"; bar::Foo foo(2); } char * prefix = "the answer="; } for(int i=0; i<4; i++) { foo.calc(i); } foo.print(prefix); return 0; }
  • 16. 5. single argument constructors should usually be explicit ~/myprog/foo.hpp ~/myprog/foo.cpp namespace bar { #include <iostream> class Foo { #include "foo.hpp" public: Foo(int seed); using namespace std; int calc(int number = 7); int getValue() { namespace bar { return value_; Foo::Foo(int seed) { } value_ = seed; void print(char* prefix); } private: int value_; int Foo::my_magic(int a, int b) { int my_magic(int a, int b); return a + b - 3 + 8 - 5; }; } } int Foo::calc(int number) { int result = my_magic(value_, number); value_ += result; ~/myprog/main.cpp return result; } #include "foo.hpp" void Foo::print(char *prefix) { int main() { cout << prefix << value_ << "n"; bar::Foo foo(2); } char * prefix = "the answer="; } for(int i=0; i<4; i++) { foo.calc(i); } foo.print(prefix); return 0; }
  • 17. 5. single argument constructors should usually be explicit ~/myprog/foo.hpp ~/myprog/foo.cpp namespace bar { #include <iostream> class Foo { #include "foo.hpp" public: explicit Foo(int seed); using namespace std; int calc(int number = 7); int getValue() { namespace bar { return value_; Foo::Foo(int seed) { } value_ = seed; void print(char* prefix); } private: int value_; int Foo::my_magic(int a, int b) { int my_magic(int a, int b); return a + b - 3 + 8 - 5; }; } } int Foo::calc(int number) { int result = my_magic(value_, number); value_ += result; ~/myprog/main.cpp return result; } #include "foo.hpp" void Foo::print(char *prefix) { int main() { cout << prefix << value_ << "n"; bar::Foo foo(2); } char * prefix = "the answer="; } for(int i=0; i<4; i++) { foo.calc(i); } foo.print(prefix); return 0; }
  • 18. 6. initialize the state of the object properly ~/myprog/foo.hpp ~/myprog/foo.cpp namespace bar { #include <iostream> class Foo { #include "foo.hpp" public: explicit Foo(int seed); using namespace std; int calc(int number = 7); int getValue() { namespace bar { return value_; Foo::Foo(int seed) { } value_ = seed; void print(char* prefix); } private: int value_; int Foo::my_magic(int a, int b) { int my_magic(int a, int b); return a + b - 3 + 8 - 5; }; } } int Foo::calc(int number) { int result = my_magic(value_, number); value_ += result; ~/myprog/main.cpp return result; } #include "foo.hpp" void Foo::print(char *prefix) { int main() { cout << prefix << value_ << "n"; bar::Foo foo(2); } char * prefix = "the answer="; } for(int i=0; i<4; i++) { foo.calc(i); } foo.print(prefix); return 0; }
  • 19. 6. initialize the state of the object properly ~/myprog/foo.hpp ~/myprog/foo.cpp namespace bar { #include <iostream> class Foo { #include "foo.hpp" public: explicit Foo(int seed); using namespace std; int calc(int number = 7); int getValue() { namespace bar { return value_; Foo::Foo(int seed) : value_(seed) { } } void print(char* prefix); private: int Foo::my_magic(int a, int b) { int value_; return a + b - 3 + 8 - 5; int my_magic(int a, int b); } }; } int Foo::calc(int number) { int result = my_magic(value_, number); value_ += result; return result; ~/myprog/main.cpp } #include "foo.hpp" void Foo::print(char *prefix) { cout << prefix << value_ << "n"; int main() { } bar::Foo foo(2); } char * prefix = "the answer="; for(int i=0; i<4; i++) { foo.calc(i); } foo.print(prefix); return 0; }
  • 20. 7. use a consistent naming convention, camelCase or under_score ~/myprog/foo.hpp ~/myprog/foo.cpp namespace bar { #include <iostream> class Foo { #include "foo.hpp" public: explicit Foo(int seed); using namespace std; int calc(int number = 7); int getValue() { namespace bar { return value_; Foo::Foo(int seed) : value_(seed) { } } void print(char* prefix); private: int Foo::my_magic(int a, int b) { int value_; return a + b - 3 + 8 - 5; int my_magic(int a, int b); } }; } int Foo::calc(int number) { int result = my_magic(value_, number); value_ += result; return result; ~/myprog/main.cpp } #include "foo.hpp" void Foo::print(char *prefix) { cout << prefix << value_ << "n"; int main() { } bar::Foo foo(2); } char * prefix = "the answer="; for(int i=0; i<4; i++) { foo.calc(i); } foo.print(prefix); return 0; }
  • 21. 7. use a consistent naming convention, camelCase or under_score ~/myprog/foo.hpp ~/myprog/foo.cpp namespace bar { #include <iostream> class Foo { #include "foo.hpp" public: explicit Foo(int seed); using namespace std; int calc(int number = 7); int getValue() { namespace bar { return value_; Foo::Foo(int seed) : value_(seed) { } } void print(char* prefix); private: int Foo::myMagic(int a, int b) { int value_; return a + b - 3 + 8 - 5; int myMagic(int a, int b); } }; } int Foo::calc(int number) { int result = myMagic(value_, number); value_ += result; return result; ~/myprog/main.cpp } #include "foo.hpp" void Foo::print(char *prefix) { cout << prefix << value_ << "n"; int main() { } bar::Foo foo(2); } char * prefix = "the answer="; for(int i=0; i<4; i++) { foo.calc(i); } foo.print(prefix); return 0; }
  • 22. 8. do not prefix queries and modifiers with get/set ~/myprog/foo.hpp ~/myprog/foo.cpp namespace bar { #include <iostream> class Foo { #include "foo.hpp" public: explicit Foo(int seed); using namespace std; int calc(int number = 7); int getValue() { namespace bar { return value_; Foo::Foo(int seed) : value_(seed) { } } void print(char* prefix); private: int Foo::myMagic(int a, int b) { int value_; return a + b - 3 + 8 - 5; int myMagic(int a, int b); } }; } int Foo::calc(int number) { int result = myMagic(value_, number); value_ += result; return result; ~/myprog/main.cpp } #include "foo.hpp" void Foo::print(char *prefix) { cout << prefix << value_ << "n"; int main() { } bar::Foo foo(2); } char * prefix = "the answer="; for(int i=0; i<4; i++) { foo.calc(i); } foo.print(prefix); return 0; }
  • 23. 8. do not prefix queries and modifiers with get/set ~/myprog/foo.hpp ~/myprog/foo.cpp namespace bar { #include <iostream> class Foo { #include "foo.hpp" public: explicit Foo(int seed); using namespace std; int calc(int number = 7); int value() { namespace bar { return value_; Foo::Foo(int seed) : value_(seed) { } } void print(char* prefix); private: int Foo::myMagic(int a, int b) { int value_; return a + b - 3 + 8 - 5; int myMagic(int a, int b); } }; } int Foo::calc(int number) { int result = myMagic(value_, number); value_ += result; return result; ~/myprog/main.cpp } #include "foo.hpp" void Foo::print(char *prefix) { cout << prefix << value_ << "n"; int main() { } bar::Foo foo(2); } char * prefix = "the answer="; for(int i=0; i<4; i++) { foo.calc(i); } foo.print(prefix); return 0; }
  • 24. 9. do not import namespaces ~/myprog/foo.hpp ~/myprog/foo.cpp namespace bar { #include <iostream> class Foo { #include "foo.hpp" public: explicit Foo(int seed); using namespace std; int calc(int number = 7); int value() { namespace bar { return value_; Foo::Foo(int seed) : value_(seed) { } } void print(char* prefix); private: int Foo::myMagic(int a, int b) { int value_; return a + b - 3 + 8 - 5; int myMagic(int a, int b); } }; } int Foo::calc(int number) { int result = myMagic(value_, number); value_ += result; return result; ~/myprog/main.cpp } #include "foo.hpp" void Foo::print(char *prefix) { cout << prefix << value_ << "n"; int main() { } bar::Foo foo(2); } char * prefix = "the answer="; for(int i=0; i<4; i++) { foo.calc(i); } foo.print(prefix); return 0; }
  • 25. 9. do not import namespaces ~/myprog/foo.hpp ~/myprog/foo.cpp namespace bar { #include <iostream> class Foo { #include "foo.hpp" public: explicit Foo(int seed); namespace bar { int calc(int number = 7); Foo::Foo(int seed) : value_(seed) { int value() { } return value_; } int Foo::myMagic(int a, int b) { void print(char* prefix); return a + b - 3 + 8 - 5; private: } int value_; int myMagic(int a, int b); int Foo::calc(int number) { }; int result = myMagic(value_, number); } value_ += result; return result; } ~/myprog/main.cpp void Foo::print(char *prefix) { std::cout << prefix << value_ << "n"; #include "foo.hpp" } } int main() { bar::Foo foo(2); char * prefix = "the answer="; for(int i=0; i<4; i++) { foo.calc(i); } foo.print(prefix); return 0; }
  • 26. 10. query functions should be declared const ~/myprog/foo.hpp ~/myprog/foo.cpp namespace bar { #include <iostream> class Foo { #include "foo.hpp" public: explicit Foo(int seed); namespace bar { int calc(int number = 7); Foo::Foo(int seed) : value_(seed) { int value() { } return value_; } int Foo::myMagic(int a, int b) { void print(char* prefix); return a + b - 3 + 8 - 5; private: } int value_; int myMagic(int a, int b); int Foo::calc(int number) { }; int result = myMagic(value_, number); } value_ += result; return result; } ~/myprog/main.cpp void Foo::print(char *prefix) { std::cout << prefix << value_ << "n"; #include "foo.hpp" } } int main() { bar::Foo foo(2); char * prefix = "the answer="; for(int i=0; i<4; i++) { foo.calc(i); } foo.print(prefix); return 0; }
  • 27. 10. query functions should be declared const ~/myprog/foo.hpp ~/myprog/foo.cpp namespace bar { #include <iostream> class Foo { #include "foo.hpp" public: explicit Foo(int seed); namespace bar { int calc(int number = 7); Foo::Foo(int seed) : value_(seed) { int value() const { } return value_; } int Foo::myMagic(int a, int b) { void print(char* prefix) const; return a + b - 3 + 8 - 5; private: } int value_; int myMagic(int a, int b); int Foo::calc(int number) { }; int result = myMagic(value_, number); } value_ += result; return result; } ~/myprog/main.cpp void Foo::print(char *prefix) const { std::cout << prefix << value_ << "n"; #include "foo.hpp" } } int main() { bar::Foo foo(2); char * prefix = "the answer="; for(int i=0; i<4; i++) { foo.calc(i); } foo.print(prefix); return 0; }
  • 28. 11. non-const functions are modifiers ~/myprog/foo.hpp ~/myprog/foo.cpp namespace bar { #include <iostream> class Foo { #include "foo.hpp" public: explicit Foo(int seed); namespace bar { int calc(int number = 7); Foo::Foo(int seed) : value_(seed) { int value() const { } ? return value_; } int Foo::myMagic(int a, int b) { void print(char* prefix) const; return a + b - 3 + 8 - 5; private: } int value_; int myMagic(int a, int b); int Foo::calc(int number) { }; int result = myMagic(value_, number); } value_ += result; return result; } ~/myprog/main.cpp void Foo::print(char *prefix) const { std::cout << prefix << value_ << "n"; #include "foo.hpp" } } int main() { bar::Foo foo(2); char * prefix = "the answer="; for(int i=0; i<4; i++) { foo.calc(i); } foo.print(prefix); return 0; }
  • 29. 12. prefer free-standing functions ~/myprog/foo.hpp ~/myprog/foo.cpp namespace bar { #include <iostream> class Foo { #include "foo.hpp" public: explicit Foo(int seed); namespace bar { int calc(int number = 7); Foo::Foo(int seed) : value_(seed) { int value() const { } return value_; } int Foo::myMagic(int a, int b) { void print(char* prefix) const; return a + b - 3 + 8 - 5; private: } int value_; int myMagic(int a, int b); int Foo::calc(int number) { }; int result = myMagic(value_, number); } value_ += result; return result; } ~/myprog/main.cpp void Foo::print(char *prefix) const { std::cout << prefix << value_ << "n"; #include "foo.hpp" } } int main() { bar::Foo foo(2); char * prefix = "the answer="; for(int i=0; i<4; i++) { foo.calc(i); } foo.print(prefix); return 0; }
  • 30. 12. prefer free-standing functions ~/myprog/foo.hpp ~/myprog/foo.cpp namespace bar { #include <iostream> class Foo { #include "foo.hpp" public: explicit Foo(int seed); namespace bar { int calc(int number = 7); Foo::Foo(int seed) : value_(seed) { int value() const { } return value_; } int Foo::myMagic(int a, int b) { void print(char* prefix) const; return a + b - 3 + 8 - 5; private: } int value_; int myMagic(int a, int b); int Foo::calc(int number) { }; int result = myMagic(value_, number); } value_ += result; return result; } ~/myprog/main.cpp void Foo::print(char *prefix) const { std::cout << prefix << value_ << "n"; #include "foo.hpp" } } int main() { bar::Foo foo(2); char * prefix = "the answer="; for(int i=0; i<4; i++) { foo.calc(i); } foo.print(prefix); return 0; }
  • 31. 12. prefer free-standing functions ~/myprog/foo.hpp ~/myprog/foo.cpp namespace bar { #include <iostream> class Foo { #include "foo.hpp" public: explicit Foo(int seed); namespace bar { int calc(int number = 7); Foo::Foo(int seed) : value_(seed) { int value() const { } return value_; } int myMagic(int a, int b) { void print(char* prefix) const; return a + b - 3 + 8 - 5; private: } int value_; }; int Foo::calc(int number) { } int result = myMagic(value_, number); value_ += result; return result; } ~/myprog/main.cpp void Foo::print(char *prefix) const { std::cout << prefix << value_ << "n"; #include "foo.hpp" } } int main() { bar::Foo foo(2); char * prefix = "the answer="; for(int i=0; i<4; i++) { foo.calc(i); } foo.print(prefix); return 0; }
  • 32. 13. use anonymous namespaces for private free-standing functions ~/myprog/foo.hpp ~/myprog/foo.cpp namespace bar { #include <iostream> class Foo { #include "foo.hpp" public: explicit Foo(int seed); namespace bar { int calc(int number = 7); Foo::Foo(int seed) : value_(seed) { int value() const { } return value_; } int myMagic(int a, int b) { void print(char* prefix) const; return a + b - 3 + 8 - 5; private: } int value_; }; int Foo::calc(int number) { } int result = myMagic(value_, number); value_ += result; return result; } ~/myprog/main.cpp void Foo::print(char *prefix) const { std::cout << prefix << value_ << "n"; #include "foo.hpp" } } int main() { bar::Foo foo(2); char * prefix = "the answer="; for(int i=0; i<4; i++) { foo.calc(i); } foo.print(prefix); return 0; }
  • 33. 13. use anonymous namespaces for private free-standing functions ~/myprog/foo.hpp ~/myprog/foo.cpp namespace bar { #include <iostream> class Foo { #include "foo.hpp" public: explicit Foo(int seed); namespace { int calc(int number = 7); int myMagic(int a, int b) { int value() const { return a + b - 3 + 8 - 5; return value_; } } } void print(char* prefix) const; private: namespace bar { int value_; Foo::Foo(int seed) : value_(seed) { }; } } int Foo::calc(int number) { int result = myMagic(value_, number); value_ += result; return result; ~/myprog/main.cpp } #include "foo.hpp" void Foo::print(char *prefix) const { std::cout << prefix << value_ << "n"; int main() { } bar::Foo foo(2); } char * prefix = "the answer="; for(int i=0; i<4; i++) { foo.calc(i); } foo.print(prefix); return 0; }
  • 34. 14. do not inline stuff in the class definition ~/myprog/foo.hpp ~/myprog/foo.cpp namespace bar { #include <iostream> class Foo { #include "foo.hpp" public: explicit Foo(int seed); namespace { int calc(int number = 7); int myMagic(int a, int b) { int value() const { return a + b - 3 + 8 - 5; return value_; } } } void print(char* prefix) const; private: namespace bar { int value_; Foo::Foo(int seed) : value_(seed) { }; } } int Foo::calc(int number) { int result = myMagic(value_, number); value_ += result; return result; ~/myprog/main.cpp } #include "foo.hpp" void Foo::print(char *prefix) const { std::cout << prefix << value_ << "n"; int main() { } bar::Foo foo(2); } char * prefix = "the answer="; for(int i=0; i<4; i++) { foo.calc(i); } foo.print(prefix); return 0; }
  • 35. 14. do not inline stuff in the class definition ~/myprog/foo.hpp ~/myprog/foo.cpp namespace bar { #include <iostream> class Foo { #include "foo.hpp" public: explicit Foo(int seed); namespace { int calc(int number = 7); int myMagic(int a, int b) { int value() const; return a + b - 3 + 8 - 5; void print(char* prefix) const; } private: } int value_; }; namespace bar { Foo::Foo(int seed) : value_(seed) { inline int Foo::value() const { } return value_; } int Foo::calc(int number) { } int result = myMagic(value_, number); value_ += result; return result; ~/myprog/main.cpp } #include "foo.hpp" void Foo::print(char *prefix) const { std::cout << prefix << value_ << "n"; int main() { } bar::Foo foo(2); } char * prefix = "the answer="; for(int i=0; i<4; i++) { foo.calc(i); } foo.print(prefix); return 0; }
  • 36. 15. by default keep your stuff in the implementation file ~/myprog/foo.hpp ~/myprog/foo.cpp namespace bar { #include <iostream> class Foo { #include "foo.hpp" public: explicit Foo(int seed); namespace { int calc(int number = 7); int myMagic(int a, int b) { int value() const; return a + b - 3 + 8 - 5; void print(char* prefix) const; } private: } int value_; }; namespace bar { Foo::Foo(int seed) : value_(seed) { inline int Foo::value() const { } return value_; } int Foo::calc(int number) { } int result = myMagic(value_, number); value_ += result; return result; ~/myprog/main.cpp } #include "foo.hpp" void Foo::print(char *prefix) const { std::cout << prefix << value_ << "n"; int main() { } bar::Foo foo(2); } char * prefix = "the answer="; for(int i=0; i<4; i++) { foo.calc(i); } foo.print(prefix); return 0; }
  • 37. 15. by default keep your stuff in the implementation file ~/myprog/foo.hpp ~/myprog/foo.cpp namespace bar { #include <iostream> class Foo { #include "foo.hpp" public: explicit Foo(int seed); namespace { int calc(int number = 7); int myMagic(int a, int b) { int value() const; return a + b - 3 + 8 - 5; void print(char* prefix) const; } private: } int value_; }; namespace bar { } Foo::Foo(int seed) : value_(seed) { } int Foo::calc(int number) { int result = myMagic(value_, number); value_ += result; return result; ~/myprog/main.cpp } #include "foo.hpp" int Foo::value() const { return value_; int main() { } bar::Foo foo(2); char * prefix = "the answer="; void Foo::print(char *prefix) const { for(int i=0; i<4; i++) { std::cout << prefix << value_ << "n"; foo.calc(i); } } } foo.print(prefix); return 0; }
  • 38. 16. avoid member functions that both modifies and queries ~/myprog/foo.hpp ~/myprog/foo.cpp namespace bar { #include <iostream> class Foo { #include "foo.hpp" public: explicit Foo(int seed); namespace { int calc(int number = 7); int myMagic(int a, int b) { int value() const; return a + b - 3 + 8 - 5; void print(char* prefix) const; } private: } int value_; }; namespace bar { } Foo::Foo(int seed) : value_(seed) { } int Foo::calc(int number) { int result = myMagic(value_, number); value_ += result; return result; ~/myprog/main.cpp } #include "foo.hpp" int Foo::value() const { return value_; int main() { } bar::Foo foo(2); char * prefix = "the answer="; void Foo::print(char *prefix) const { for(int i=0; i<4; i++) { std::cout << prefix << value_ << "n"; foo.calc(i); } } } foo.print(prefix); return 0; }
  • 39. 16. avoid member functions that both modifies and queries ~/myprog/foo.hpp ~/myprog/foo.cpp namespace bar { #include <iostream> class Foo { #include "foo.hpp" public: explicit Foo(int seed); namespace { void calc(int number = 7); int myMagic(int a, int b) { int value() const; return a + b - 3 + 8 - 5; void print(char* prefix) const; } private: } int value_; }; namespace bar { } Foo::Foo(int seed) : value_(seed) { } void Foo::calc(int number) { value_ += myMagic(value_, number); } ~/myprog/main.cpp int Foo::value() const { return value_; #include "foo.hpp" } int main() { void Foo::print(char *prefix) const { bar::Foo foo(2); std::cout << prefix << value_ << "n"; char * prefix = "the answer="; } for(int i=0; i<4; i++) { } foo.calc(i); } foo.print(prefix); return 0; }
  • 40. 17. default arguments are depreciated, use delegation if you must ~/myprog/foo.hpp ~/myprog/foo.cpp namespace bar { #include <iostream> class Foo { #include "foo.hpp" public: explicit Foo(int seed); namespace { void calc(int number = 7); int myMagic(int a, int b) { int value() const; return a + b - 3 + 8 - 5; void print(char* prefix) const; } private: } int value_; }; namespace bar { } Foo::Foo(int seed) : value_(seed) { } void Foo::calc(int number) { value_ += myMagic(value_, number); } ~/myprog/main.cpp int Foo::value() const { return value_; #include "foo.hpp" } int main() { void Foo::print(char *prefix) const { bar::Foo foo(2); std::cout << prefix << value_ << "n"; char * prefix = "the answer="; } for(int i=0; i<4; i++) { } foo.calc(i); } foo.print(prefix); return 0; }
  • 41. 17. default arguments are depreciated, use delegation if you must ~/myprog/foo.hpp ~/myprog/foo.cpp namespace bar { #include <iostream> class Foo { #include "foo.hpp" public: explicit Foo(int seed); namespace { void calc(int number); int myMagic(int a, int b) { int value() const; return a + b - 3 + 8 - 5; void print(char* prefix) const; } private: } int value_; }; namespace bar { } Foo::Foo(int seed) : value_(seed) { } void Foo::calc(int number) { value_ += myMagic(value_, number); } ~/myprog/main.cpp int Foo::value() const { return value_; #include "foo.hpp" } int main() { void Foo::print(char *prefix) const { bar::Foo foo(2); std::cout << prefix << value_ << "n"; char * prefix = "the answer="; } for(int i=0; i<4; i++) { } foo.calc(i); } foo.print(prefix); return 0; }
  • 42. 18. the K&R vs BS war is over, use an extra space around & and * ~/myprog/foo.hpp ~/myprog/foo.cpp namespace bar { #include <iostream> class Foo { #include "foo.hpp" public: explicit Foo(int seed); namespace { void calc(int number); int myMagic(int a, int b) { int value() const; return a + b - 3 + 8 - 5; void print(char* prefix) const; } private: } int value_; }; namespace bar { } Foo::Foo(int seed) : value_(seed) { } void Foo::calc(int number) { value_ += myMagic(value_, number); } ~/myprog/main.cpp int Foo::value() const { return value_; #include "foo.hpp" } int main() { void Foo::print(char *prefix) const { bar::Foo foo(2); std::cout << prefix << value_ << "n"; char * prefix = "the answer="; } for(int i=0; i<4; i++) { } foo.calc(i); } foo.print(prefix); return 0; }
  • 43. 18. the K&R vs BS war is over, use an extra space around & and * ~/myprog/foo.hpp ~/myprog/foo.cpp namespace bar { #include <iostream> class Foo { #include "foo.hpp" public: explicit Foo(int seed); namespace { void calc(int number); int myMagic(int a, int b) { int value() const; return a + b - 3 + 8 - 5; void print(char * prefix) const; } private: } int value_; }; namespace bar { } Foo::Foo(int seed) : value_(seed) { } void Foo::calc(int number) { value_ += myMagic(value_, number); } ~/myprog/main.cpp int Foo::value() const { return value_; #include "foo.hpp" } int main() { void Foo::print(char * prefix) const { bar::Foo foo(2); std::cout << prefix << value_ << "n"; char * prefix = "the answer="; } for(int i=0; i<4; i++) { } foo.calc(i); } foo.print(prefix); return 0; }
  • 44. 19. by not specifying const you say that something will change ~/myprog/foo.hpp ~/myprog/foo.cpp namespace bar { #include <iostream> class Foo { #include "foo.hpp" public: explicit Foo(int seed); namespace { void calc(int number); int myMagic(int a, int b) { int value() const; return a + b - 3 + 8 - 5; void print(char * prefix) const; } private: } int value_; }; namespace bar { } Foo::Foo(int seed) : value_(seed) { } void Foo::calc(int number) { value_ += myMagic(value_, number); } ~/myprog/main.cpp int Foo::value() const { return value_; #include "foo.hpp" } int main() { void Foo::print(char * prefix) const { bar::Foo foo(2); std::cout << prefix << value_ << "n"; char * prefix = "the answer="; } for(int i=0; i<4; i++) { } foo.calc(i); } foo.print(prefix); return 0; }
  • 45. 19. by not specifying const you say that something will change ~/myprog/foo.hpp ~/myprog/foo.cpp namespace bar { #include <iostream> class Foo { #include "foo.hpp" public: explicit Foo(int seed); namespace { void calc(int number); int myMagic(int a, int b) { int value() const; return a + b - 3 + 8 - 5; void print(const char * prefix) const; } private: } int value_; }; namespace bar { } Foo::Foo(int seed) : value_(seed) { } void Foo::calc(int number) { value_ += myMagic(value_, number); } ~/myprog/main.cpp int Foo::value() const { return value_; #include "foo.hpp" } int main() { void Foo::print(const char * prefix) const { bar::Foo foo(2); std::cout << prefix << value_ << "n"; const char * prefix = "the answer="; } for(int i=0; i<4; i++) { } foo.calc(i); } foo.print(prefix); return 0; }
  • 46. 20. reduce scope of variables ~/myprog/foo.hpp ~/myprog/foo.cpp namespace bar { #include <iostream> class Foo { #include "foo.hpp" public: explicit Foo(int seed); namespace { void calc(int number); int myMagic(int a, int b) { int value() const; return a + b - 3 + 8 - 5; void print(const char * prefix) const; } private: } int value_; }; namespace bar { } Foo::Foo(int seed) : value_(seed) { } void Foo::calc(int number) { value_ += myMagic(value_, number); } ~/myprog/main.cpp int Foo::value() const { return value_; #include "foo.hpp" } int main() { void Foo::print(const char * prefix) const { bar::Foo foo(2); std::cout << prefix << value_ << "n"; const char * prefix = "the answer="; } for(int i=0; i<4; i++) { } foo.calc(i); } foo.print(prefix); return 0; }
  • 47. 20. reduce scope of variables ~/myprog/foo.hpp ~/myprog/foo.cpp namespace bar { #include <iostream> class Foo { #include "foo.hpp" public: explicit Foo(int seed); namespace { void calc(int number); int myMagic(int a, int b) { int value() const; return a + b - 3 + 8 - 5; void print(const char * prefix) const; } private: } int value_; }; namespace bar { } Foo::Foo(int seed) : value_(seed) { } void Foo::calc(int number) { value_ += myMagic(value_, number); } ~/myprog/main.cpp int Foo::value() const { return value_; #include "foo.hpp" } int main() { void Foo::print(const char * prefix) const { bar::Foo foo(2); std::cout << prefix << value_ << "n"; for(int i=0; i<4; i++) { } foo.calc(i); } } const char * prefix = "the answer="; foo.print(prefix); return 0; }
  • 48. 21. for-loops in C++ are often not written like this ~/myprog/foo.hpp ~/myprog/foo.cpp namespace bar { #include <iostream> class Foo { #include "foo.hpp" public: explicit Foo(int seed); namespace { void calc(int number); int myMagic(int a, int b) { int value() const; return a + b - 3 + 8 - 5; void print(const char * prefix) const; } private: } int value_; }; namespace bar { } Foo::Foo(int seed) : value_(seed) { } void Foo::calc(int number) { value_ += myMagic(value_, number); } ~/myprog/main.cpp int Foo::value() const { return value_; #include "foo.hpp" } int main() { void Foo::print(const char * prefix) const { bar::Foo foo(2); std::cout << prefix << value_ << "n"; for(int i=0; i<4; i++) { } foo.calc(i); } } const char * prefix = "the answer="; foo.print(prefix); return 0; }
  • 49. 21. for-loops in C++ are often not written like this ~/myprog/foo.hpp ~/myprog/foo.cpp namespace bar { #include <iostream> class Foo { #include "foo.hpp" public: explicit Foo(int seed); namespace { void calc(int number); int myMagic(int a, int b) { int value() const; return a + b - 3 + 8 - 5; void print(const char * prefix) const; } private: } int value_; }; namespace bar { } Foo::Foo(int seed) : value_(seed) { } void Foo::calc(int number) { value_ += myMagic(value_, number); } ~/myprog/main.cpp int Foo::value() const { return value_; #include "foo.hpp" } int main() { void Foo::print(const char * prefix) const { bar::Foo foo(2); std::cout << prefix << value_ << "n"; for (int i = 0; i != 4; ++i) { } foo.calc(i); } } const char * prefix = "the answer="; foo.print(prefix); return 0; }
  • 50. 22. in C++ you do not need to explicitly return from main ~/myprog/foo.hpp ~/myprog/foo.cpp namespace bar { #include <iostream> class Foo { #include "foo.hpp" public: explicit Foo(int seed); namespace { void calc(int number); int myMagic(int a, int b) { int value() const; return a + b - 3 + 8 - 5; void print(const char * prefix) const; } private: } int value_; }; namespace bar { } Foo::Foo(int seed) : value_(seed) { } void Foo::calc(int number) { value_ += myMagic(value_, number); } ~/myprog/main.cpp int Foo::value() const { return value_; #include "foo.hpp" } int main() { void Foo::print(const char * prefix) const { bar::Foo foo(2); std::cout << prefix << value_ << "n"; for (int i = 0; i != 4; ++i) { } foo.calc(i); } } const char * prefix = "the answer="; foo.print(prefix); return 0; }
  • 51. 22. in C++ you do not need to explicitly return from main ~/myprog/foo.hpp ~/myprog/foo.cpp namespace bar { #include <iostream> class Foo { #include "foo.hpp" public: explicit Foo(int seed); namespace { void calc(int number); int myMagic(int a, int b) { int value() const; return a + b - 3 + 8 - 5; void print(const char * prefix) const; } private: } int value_; }; namespace bar { } Foo::Foo(int seed) : value_(seed) { } void Foo::calc(int number) { value_ += myMagic(value_, number); } ~/myprog/main.cpp int Foo::value() const { return value_; #include "foo.hpp" } int main() { void Foo::print(const char * prefix) const { bar::Foo foo(2); std::cout << prefix << value_ << "n"; for (int i = 0; i != 4; ++i) { } foo.calc(i); } } const char * prefix = "the answer="; foo.print(prefix); return 0; }
  • 52. 22. in C++ you do not need to explicitly return from main ~/myprog/foo.hpp ~/myprog/foo.cpp namespace bar { #include <iostream> class Foo { #include "foo.hpp" public: explicit Foo(int seed); namespace { void calc(int number); int myMagic(int a, int b) { int value() const; return a + b - 3 + 8 - 5; void print(const char * prefix) const; } private: } int value_; }; namespace bar { } Foo::Foo(int seed) : value_(seed) { } void Foo::calc(int number) { value_ += myMagic(value_, number); } ~/myprog/main.cpp int Foo::value() const { return value_; #include "foo.hpp" } int main() { void Foo::print(const char * prefix) const { bar::Foo foo(2); std::cout << prefix << value_ << "n"; for (int i = 0; i != 4; ++i) { } foo.calc(i); } } const char * prefix = "the answer="; foo.print(prefix); }
  • 53. 23. inject side-effects if you must have them ~/myprog/foo.hpp ~/myprog/foo.cpp namespace bar { #include <iostream> class Foo { #include "foo.hpp" public: explicit Foo(int seed); namespace { void calc(int number); int myMagic(int a, int b) { int value() const; return a + b - 3 + 8 - 5; void print(const char * prefix) const; } private: } int value_; }; namespace bar { } Foo::Foo(int seed) : value_(seed) { } void Foo::calc(int number) { value_ += myMagic(value_, number); } ~/myprog/main.cpp int Foo::value() const { return value_; #include "foo.hpp" } int main() { void Foo::print(const char * prefix) const { bar::Foo foo(2); std::cout << prefix << value_ << "n"; for (int i = 0; i != 4; ++i) { } foo.calc(i); } } const char * prefix = "the answer="; foo.print(prefix); }
  • 54. 23. inject side-effects if you must have them ~/myprog/foo.hpp ~/myprog/foo.cpp namespace bar { #include <ostream> class Foo { #include "foo.hpp" public: explicit Foo(int seed); namespace { void calc(int number); int myMagic(int a, int b) { int value() const; return a + b - 3 + 8 - 5; void print(std::ostream & out, } const char * prefix) const; } private: int value_; namespace bar { }; Foo::Foo(int seed) : value_(seed) { } } void Foo::calc(int number) { value_ += myMagic(value_, number); } ~/myprog/main.cpp int Foo::value() const { return value_; #include <iostream> } #include "foo.hpp" void Foo::print(std::ostream & out, int main() { const char * prefix) const { bar::Foo foo(2); out << prefix << value_ << "n"; for (int i = 0; i != 4; ++i) { } foo.calc(i); } } const char * prefix = "the answer="; foo.print(std::cout, prefix); }
  • 55. 24. make sure headers compile by itself ~/myprog/foo.hpp ~/myprog/foo.cpp namespace bar { #include <ostream> class Foo { #include "foo.hpp" public: explicit Foo(int seed); namespace { void calc(int number); int myMagic(int a, int b) { int value() const; return a + b - 3 + 8 - 5; void print(std::ostream & out, } const char * prefix) const; } private: int value_; namespace bar { }; Foo::Foo(int seed) : value_(seed) { } } void Foo::calc(int number) { value_ += myMagic(value_, number); } ~/myprog/main.cpp int Foo::value() const { return value_; #include <iostream> } #include "foo.hpp" void Foo::print(std::ostream & out, int main() { const char * prefix) const { bar::Foo foo(2); out << prefix << value_ << "n"; for (int i = 0; i != 4; ++i) { } foo.calc(i); } } const char * prefix = "the answer="; foo.print(std::cout, prefix); }
  • 56. 24. make sure headers compile by itself ~/myprog/foo.hpp ~/myprog/foo.cpp #include <iostream> #include <ostream> #include "foo.hpp" namespace bar { class Foo { namespace { public: int myMagic(int a, int b) { explicit Foo(int seed); return a + b - 3 + 8 - 5; void calc(int number); } int value() const; } void print(std::ostream & out, const char * prefix) const; namespace bar { private: Foo::Foo(int seed) : value_(seed) { int value_; } }; } void Foo::calc(int number) { value_ += myMagic(value_, number); } ~/myprog/main.cpp int Foo::value() const { return value_; #include <iostream> } #include "foo.hpp" void Foo::print(std::ostream & out, int main() { const char * prefix) const { bar::Foo foo(2); out << prefix << value_ << "n"; for (int i = 0; i != 4; ++i) { } foo.calc(i); } } const char * prefix = "the answer="; foo.print(std::cout, prefix); }
  • 57. 25. include your own header file first, standard libraries last ~/myprog/foo.hpp ~/myprog/foo.cpp #include <iostream> #include <ostream> #include "foo.hpp" namespace bar { class Foo { namespace { public: int myMagic(int a, int b) { explicit Foo(int seed); return a + b - 3 + 8 - 5; void calc(int number); } int value() const; } void print(std::ostream & out, const char * prefix) const; namespace bar { private: Foo::Foo(int seed) : value_(seed) { int value_; } }; } void Foo::calc(int number) { value_ += myMagic(value_, number); } ~/myprog/main.cpp int Foo::value() const { return value_; #include <iostream> } #include "foo.hpp" void Foo::print(std::ostream & out, int main() { const char * prefix) const { bar::Foo foo(2); out << prefix << value_ << "n"; for (int i = 0; i != 4; ++i) { } foo.calc(i); } } const char * prefix = "the answer="; foo.print(std::cout, prefix); }
  • 58. 25. include your own header file first, standard libraries last ~/myprog/foo.hpp ~/myprog/foo.cpp #include <iostream> #include "foo.hpp" #include <ostream> namespace bar { class Foo { namespace { public: int myMagic(int a, int b) { explicit Foo(int seed); return a + b - 3 + 8 - 5; void calc(int number); } int value() const; } void print(std::ostream & out, const char * prefix) const; namespace bar { private: Foo::Foo(int seed) : value_(seed) { int value_; } }; } void Foo::calc(int number) { value_ += myMagic(value_, number); } ~/myprog/main.cpp int Foo::value() const { return value_; #include "foo.hpp" } #include <iostream> void Foo::print(std::ostream & out, int main() { const char * prefix) const { bar::Foo foo(2); out << prefix << value_ << "n"; for (int i = 0; i != 4; ++i) { } foo.calc(i); } } const char * prefix = "the answer="; foo.print(std::cout, prefix); }
  • 59. 26. prefer forward declarations in header files ~/myprog/foo.hpp ~/myprog/foo.cpp #include <iostream> #include "foo.hpp" #include <ostream> namespace bar { class Foo { namespace { public: int myMagic(int a, int b) { explicit Foo(int seed); return a + b - 3 + 8 - 5; void calc(int number); } int value() const; } void print(std::ostream & out, const char * prefix) const; namespace bar { private: Foo::Foo(int seed) : value_(seed) { int value_; } }; } void Foo::calc(int number) { value_ += myMagic(value_, number); } ~/myprog/main.cpp int Foo::value() const { return value_; #include "foo.hpp" } #include <iostream> void Foo::print(std::ostream & out, int main() { const char * prefix) const { bar::Foo foo(2); out << prefix << value_ << "n"; for (int i = 0; i != 4; ++i) { } foo.calc(i); } } const char * prefix = "the answer="; foo.print(std::cout, prefix); }
  • 60. 26. prefer forward declarations in header files ~/myprog/foo.hpp ~/myprog/foo.cpp #include <iosfwd> #include "foo.hpp" #include <ostream> namespace bar { class Foo { namespace { public: int myMagic(int a, int b) { explicit Foo(int seed); return a + b - 3 + 8 - 5; void calc(int number); } int value() const; } void print(std::ostream & out, const char * prefix) const; namespace bar { private: Foo::Foo(int seed) : value_(seed) { int value_; } }; } void Foo::calc(int number) { value_ += myMagic(value_, number); } ~/myprog/main.cpp int Foo::value() const { return value_; #include "foo.hpp" } #include <iostream> void Foo::print(std::ostream & out, int main() { const char * prefix) const { bar::Foo foo(2); out << prefix << value_ << "n"; for (int i = 0; i != 4; ++i) { } foo.calc(i); } } const char * prefix = "the answer="; foo.print(std::cout, prefix); }
  • 61. 27. don't need braces here ~/myprog/foo.hpp ~/myprog/foo.cpp #include <iosfwd> #include "foo.hpp" #include <ostream> namespace bar { class Foo { namespace { public: int myMagic(int a, int b) { explicit Foo(int seed); return a + b - 3 + 8 - 5; void calc(int number); } int value() const; } void print(std::ostream & out, const char * prefix) const; namespace bar { private: Foo::Foo(int seed) : value_(seed) { int value_; } }; } void Foo::calc(int number) { value_ += myMagic(value_, number); } ~/myprog/main.cpp int Foo::value() const { return value_; #include "foo.hpp" } #include <iostream> void Foo::print(std::ostream & out, int main() { const char * prefix) const { bar::Foo foo(2); out << prefix << value_ << "n"; for (int i = 0; i != 4; ++i) { } foo.calc(i); } } const char * prefix = "the answer="; foo.print(std::cout, prefix); }
  • 62. 27. don't need braces here ~/myprog/foo.hpp ~/myprog/foo.cpp #include <iosfwd> #include "foo.hpp" #include <ostream> namespace bar { class Foo { namespace { public: int myMagic(int a, int b) { explicit Foo(int seed); return a + b - 3 + 8 - 5; void calc(int number); } int value() const; } void print(std::ostream & out, const char * prefix) const; namespace bar { private: Foo::Foo(int seed) : value_(seed) { int value_; } }; } void Foo::calc(int number) { value_ += myMagic(value_, number); } ~/myprog/main.cpp int Foo::value() const { return value_; #include "foo.hpp" } #include <iostream> void Foo::print(std::ostream & out, int main() { const char * prefix) const { bar::Foo foo(2); out << prefix << value_ << "n"; for (int i = 0; i != 4; ++i) } foo.calc(i); } const char * prefix = "the answer="; foo.print(std::cout, prefix); }
  • 63. 28. avoid side-effects if you can, prefer free-standing functions ~/myprog/foo.hpp ~/myprog/foo.cpp #include <iosfwd> #include "foo.hpp" #include <ostream> namespace bar { class Foo { namespace { public: int myMagic(int a, int b) { explicit Foo(int seed); return a + b - 3 + 8 - 5; void calc(int number); } int value() const; } void print(std::ostream & out, const char * prefix) const; namespace bar { private: Foo::Foo(int seed) : value_(seed) { int value_; } }; } void Foo::calc(int number) { value_ += myMagic(value_, number); } ~/myprog/main.cpp int Foo::value() const { return value_; #include "foo.hpp" } #include <iostream> void Foo::print(std::ostream & out, int main() { const char * prefix) const { bar::Foo foo(2); out << prefix << value_ << "n"; for (int i = 0; i != 4; ++i) } foo.calc(i); } const char * prefix = "the answer="; foo.print(std::cout, prefix); }
  • 64. 28. avoid side-effects if you can, prefer free-standing functions ~/myprog/foo.hpp ~/myprog/foo.cpp #include <iosfwd> #include "foo.hpp" #include <ostream> namespace bar { class Foo { namespace { public: int myMagic(int a, int b) { explicit Foo(int seed); return a + b - 3 + 8 - 5; void calc(int number); } int value() const; } private: int value_; namespace bar { }; Foo::Foo(int seed) : value_(seed) { void print(std::ostream & out, } const char * prefix, const Foo & foo); void Foo::calc(int number) { } value_ += myMagic(value_, number); } ~/myprog/main.cpp int Foo::value() const { return value_; #include "foo.hpp" } #include <iostream> void print(std::ostream & out, int main() { const char * prefix, bar::Foo foo(2); const Foo & foo) { for (int i = 0; i != 4; ++i) out << prefix << foo.value() << "n"; foo.calc(i); } const char * prefix = "the answer="; } print(std::cout, prefix, foo); }
  • 65. 29. do not open a namespace when implementing free-standing functions ~/myprog/foo.hpp ~/myprog/foo.cpp #include <iosfwd> #include "foo.hpp" #include <ostream> namespace bar { class Foo { namespace { public: int myMagic(int a, int b) { explicit Foo(int seed); return a + b - 3 + 8 - 5; void calc(int number); } int value() const; } private: int value_; namespace bar { }; Foo::Foo(int seed) : value_(seed) { void print(std::ostream & out, } const char * prefix, const Foo & foo); void Foo::calc(int number) { } value_ += myMagic(value_, number); } ~/myprog/main.cpp int Foo::value() const { return value_; #include "foo.hpp" } #include <iostream> void print(std::ostream & out, int main() { const char * prefix, bar::Foo foo(2); const Foo & foo) { for (int i = 0; i != 4; ++i) out << prefix << foo.value() << "n"; foo.calc(i); } const char * prefix = "the answer="; } print(std::cout, prefix, foo); }
  • 66. 29. do not open a namespace when implementing free-standing functions ~/myprog/foo.hpp ~/myprog/foo.cpp #include <iosfwd> #include "foo.hpp" #include <ostream> namespace bar { class Foo { namespace { public: int myMagic(int a, int b) { explicit Foo(int seed); return a + b - 3 + 8 - 5; void calc(int number); } int value() const; } private: int value_; namespace bar { }; Foo::Foo(int seed) : value_(seed) { void print(std::ostream & out, } const char * prefix, const Foo & foo); void Foo::calc(int number) { } value_ += myMagic(value_, number); } ~/myprog/main.cpp int Foo::value() const { return value_; #include "foo.hpp" } #include <iostream> } int main() { void bar::print(std::ostream & out, bar::Foo foo(2); const char * prefix, for (int i = 0; i != 4; ++i) const bar::Foo & foo) { foo.calc(i); out << prefix << foo.value() << "n"; const char * prefix = "the answer="; } print(std::cout, prefix, foo); }
  • 67. 30. operator overloading is sometimes a nice thing ~/myprog/foo.hpp ~/myprog/foo.cpp #include <iosfwd> #include "foo.hpp" #include <ostream> namespace bar { class Foo { namespace { public: int myMagic(int a, int b) { explicit Foo(int seed); return a + b - 3 + 8 - 5; void calc(int number); } int value() const; } private: int value_; namespace bar { }; Foo::Foo(int seed) : value_(seed) { void print(std::ostream & out, } const char * prefix, const Foo & foo); void Foo::calc(int number) { } value_ += myMagic(value_, number); } ~/myprog/main.cpp int Foo::value() const { return value_; #include "foo.hpp" } #include <iostream> } int main() { void bar::print(std::ostream & out, bar::Foo foo(2); const char * prefix, for (int i = 0; i != 4; ++i) const bar::Foo & foo) { foo.calc(i); out << prefix << foo.value() << "n"; const char * prefix = "the answer="; } print(std::cout, prefix, foo); }