1 / 30

Brown Bag #3

Brown Bag #3. Return of the C ++. Topics. Common C++ “Gotchas” Polymorphism Best Practices Useful Titbits. Common C++ “Gotchas”. Circular dependencies Slicing Rule of Three. // file: A.h class B; class A { B& _b; }; // file: B.h class A; class B { A& _a; }; .

holden
Download Presentation

Brown Bag #3

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Brown Bag #3 Return of the C++

  2. Topics • Common C++ “Gotchas” • Polymorphism • Best Practices • Useful Titbits

  3. Common C++ “Gotchas” • Circular dependencies • Slicing • Rule of Three

  4. // file: A.h • classB; • classA • { • B& _b; • }; • // file: B.h • classA; • class B • { • A& _a; • }; // file: A.h • #include “B.h” class A { B _b; }; // file: B.h • #include "A.h” class B { A _a; }; Circular Dependencies • Problem: • Two classes that depend on each other • Can’t use #include in both headers • Solution: • Use forward declarations! • Use (smart) pointers / references for members • Limit includes in headers (helps compilation)

  5. Rule of Three • If you define one of these, define all three: • Destructor • Copy constructor • Assignment operator • Otherwise implicitly generated • Latter 2 copy all class members • Copies pointers not objects • Want move/swap semantics? • Call base version from derived classes • Rule of Two: RAII destructors MyClass& MyClass::operator= (constMyClass& other) { if(this != &other) { // Do stuff } return*this; }

  6. Slicing • Problem: • Loss of derived class functionality • Occurs when derived class copied into base class • Especially when passing by value • Solution: • Pass by reference or pointer! • Avoid concrete base classes voidFoo( BaseClassbaseParam); ... DerivedClassmyDerived; Foo( myDerived );

  7. Polymorphism • ‘virtual’ • Implicit Override • Explicit Override • ‘final’ • Abstract Classes • Interfaces • Multiple Inheritance • Virtual Class Inheritance

  8. ‘virtual’ • Used to declare virtual functions. • Virtual functions can have functionality overwritten in child classes. classAnimal { virtualintGetNumLegs(); }; classDog:publicAnimal { virtualintGetNumLegs(); }; classOctopus:publicAnimal { virtualintGetNumLegs(); }; intAnimal::GetNumLegs() { return 0; } intDog::GetNumLegs() { return 4; } intOctopus::GetNumLegs() { return 8; }

  9. Implicit Override • C++ traditionally does not require use of the ‘override’ keyword. classParent { virtualvoidFoo(inti); }; classChild :publicParent { virtualvoidFoo(floati); }; • Child::Foo does not override Parent::Foo as they have different signatures. • Compiler will not raise an error over this – this is valid declaration.

  10. Explicit Override • C++11 introduces the ‘override’ keyword to ensure virtual functions are overwritten. classParent { virtualvoidFoo(inti); }; classChild :publicParent { virtualvoidFoo(floati)override; }; • If the base class does not contain a virtual function with the same signature, the compiler will throw an error. • Useful to ensure functions are overwritten correctly.

  11. ‘final’ • C++11 also introduces the ‘final’ keyword. • This ensures that a virtual function cannot be overwritten in child classes. classParent { virtualvoidFoo() final; }; classChild :publicParent { virtualvoidFoo()override; }; • Attempting to override a virtual function declared as final will cause the compiler to throw an error.

  12. Abstract Classes • An abstract class is one which you cannot instantiate. • Contains virtual function(s) which must be overwritten in the child class. • A class is abstract if it contains at least pure virtual function. classParent { virtualvoidFoo() = 0; }; classChild :publicParent { virtualvoidFoo(); }; ParentparentObject; // ERROR ChildchildObject; // OK

  13. Interfaces • Similar to an abstract class whose functions are all pure virtual. • Defines certain functionality that a class must implement. • Implementation of functions is individual to each class. __interfaceIDancer { voidDance(); }; classFireman:publicIDancer { virtualvoidDance(); }; classButcher:publicIDancer { virtualvoidDance(); };

  14. Interfaces (cont.) • Objects that implement an interface can be cast to their interface type. • Allows for easy communication between otherwise unrelated object types. • Easier manipulation of objects. std::vector<IDancer> dancers; Firemanfireman; Butcherbutcher; dancers.push_back(fireman); dancers.push_back(butcher); std::for_each(dancers.begin(), dancers.end(), [](IDancerdancer) { dancer.Dance(); });

  15. Multiple Inheritance Animal • Consider the following example: classAnimal { virtualvoidEat(); }; classMammal : publicAnimal { … }; classWingedAnimal: publicAnimal { … }; classBat : publicMammal, publicWingedAnimal { … }; Mammal WingedAnimal Bat

  16. Multiple Inheritance (cont). • If we call Bat::Eat(), which function do we call? • It is an ambiguous function call. • This is because we have two Animal base classes. • Static cast to Animal is also ambiguous.

  17. Virtual Class Inheritance • We can use the ‘virtual’ keyword when inheriting from a class: classAnimal { virtualvoidEat(); }; classMammal : publicvirtualAnimal { … }; classWingedAnimal: publicvirtualAnimal { … }; classBat : publicMammal, publicWingedAnimal { … };

  18. Virtual Class Inheritance (cont.) • The ‘virtual’ keyword will ensure that when a Bat object is created, the Animal instance used by Mammal and WingedAnimal will be the same. • This will remove any ambiguity from calls to Bat::Eat(). • Will also allow direct casting of Bat to Animal.

  19. Best Practices • Const WTF • Const FTW • Preprocessor FTL • Enums FTW

  20. Const WTF constThing* a = new Thing(); Thing const* b = newThing(); Thing* constc = newThing(); constThing* constd = newThing(); • Pointer to constant object - Pointer cannot change object • Same as 1. • Constant pointer to object - Pointer itself cannot change • All the const - Neither pointe or pointed can change

  21. Const FTW voidFoo( Thinginput); voidFoo( Thinginput); • Prefer pass-by-reference-to-const to pass-by-value (item #20) • Avoids unnecessary constructors/destructor calls • Still guarantee to caller that object won’t be changed voidFoo( constThing& input); voidFoo( Thing const& input); • const member functions (getters) ThingGetData() const;

  22. Preprocessor FTL #defineSuperImportant = 42; #defineSuperImportant = 42; constintSuperImportant = 42; • Avoid #define literals • Not type-safe • Not scoped • Use initialized constant instead #defineMAX(a, b) ((a < b) ? b : a); #defineMAX(a, b) ((a < b) ? b : a); inlineint MAX(inta, intb) { return(a < b) ? b : a; } • Avoid #define pseudo-functions • Look like function calls, aren’t • Same type/scope problems • Use initialized constant instead

  23. Enums FTW • Nicer and safer than preprocessor definitions • Enum classes/structs (C++ 11) • Old: Wrap Enums in struct • Now type-safe in C++ 11 structMyEnum { enumEnum { MAX }; }; enumclassMyEnum { MAX };

  24. Useful Titbits • Type Inference • Range-Based For Loop • Singleton Design Pattern • Treat Warnings as Errors • Visual Assist X

  25. Type Inference (decltype) • C++11 introduces ‘decltype’ which can be used to infer the type of an object based on the declared value of another. • Useful in conjunction with ‘auto’ when heavy operator overloading and casting is required. charFoo(); inti = 0; decltype(i) a; // a is an int decltype(0) b; // b is an int decltype(Foo()) c; // c is a char

  26. Ranged-Based For Loop • An easier way to iterate through all the elements in a sequence of objects. • Supported by: • C-style arrays • Initializer lists • Types that implement begin() and end() iterators (STL Containers). intmyArray[6] = {1, 2, 3, 4, 5, 6}; intarrayTotal = 0; for (int &i : myArray) { arrayTotal += i; } std::cout<< “The sum of all values is “ << arrayTotal << “.\n”; // 21

  27. Singleton Pattern classS { public: staticS& getInstance() { staticS instance; returninstance; } private: S(Sconst&); // Don't implement voidoperator=(Sconst&); }; • Limit to one class instance • No public constructors • Single static instance • Semi-controversial design pattern • Don’t overuse it Stolen from: http://stackoverflow.com/questions/1008019/c-singleton-design-pattern

  28. Treat Warnings as Errors

  29. Visual Assist X • Intellisense++ • Refactoring • Improved syntax highlighting • Keyboard shortcuts • Jump between header/source • £30 for students

  30. Further Reading • Microsoft Developers Network (MSDN) • CPlusPlus.com

More Related