230 likes | 249 Views
Learn the key features of C++ used in Geant4, including inheritance, singletons, templates, and more. Understand class, constructor/destructor, methods, arguments, and operator overloading.
E N D
C++ for Geant4 users A collection of most useful and/or common features used in and to use Geant4 Marc Verderi LLR – Ecole polytechnique Marc Verderi - LLR Ecole polytechnique
Introduction • Geant4 user’s interfaces do not involve “expert” C++ features. • The most advanced features exposed to the user: • Inheritance • The feature that makes a programming language “Object Oriented” • And which makes Geant4 versatile and extendable • Singletons • Which is the technique used for the many “managers” in Geant4 • A little of templates • The so-called “generic programming” • Hope here is to make novice users a bit more comfortable with the above: • Assuming basic syntax is known (int, double, i++, for(…){..}, etc…) • Speak about • Class • constructor/destructor, methods & arguments, const, initialization and operator overloading • Inheritance • Singleton Marc Verderi - LLR Ecole polytechnique
Class Marc Verderi - LLR Ecole polytechnique
Class : constructor/destructor Class declaration: class AClass { public: // default constructor: AClass(); // copy constructor: AClass(const AClass &); // other constructor: AClass([arguments]); // destructor ~AClass(); … … }; At use: #include “AClass.hh” … [some main, method…]{ … AClass objA; … AClass objB(objA); … AClass objC([arg. values]); … AClass *p_obj = new AClass; … } // here, destructor called // for objA, objB, objC, // but not for *p_obj that // requires delete p_obj; Used when object passed by value. Heavily used by STL: eg std::vector<T>, when increasing vector capacity Marc Verderi - LLR Ecole polytechnique
Class : method & arguments Class declaration: class AClass { … … public: int fun1(int i); // default argument: double fun2(int n=0); // argument type: double fun2(double); // !! Ambiguity here !! double fun2(double w=3.14); // !! not allowed !! int fun2(double); … }; At use: #include “AClass.hh” … [some main, method…]{ … AClass objA; int i = objA.fun1(5); … double x = objA.fun2(); … double z = objA.fun2(3.14); // is it n=0 or w=3.14 ? double v = objA.fun2(); Marc Verderi - LLR Ecole polytechnique
Class : “publicity” levels Class declaration: class AClass { … public: // access to everyone: int publicFun(); protected: // access to derived classes: double protectFun(); … private: // access to this class only // (and “friend” classes) void privateFun(); int someNumber; … }; At use: #include “AClass.hh” … [some main, method…]{ … AClass objA; int i = objA.publicFun(); … // valid only in derived // classes code (see later): double a = objA.protectFun(); … // valid only in AClass code: objA.privateFun(); int m = objA.someNumber; Marc Verderi - LLR Ecole polytechnique
Class : keyword const Class declaration: class AClass { … public: // pointing to constant int const int* add(int i) {someNumber += i; return &someNumber;} // object itself unaffected: int number() const {return someNumber;} // !! Wrong !! void increment() const {someNumber++;} private: int someNumber; }; At use: #include “AClass.hh” … [some main, method…]{ AClass objA; const int* j = objA.add(5); // !! Wrong !! int *n = objA.add(5); … int k = objA.number(); … Marc Verderi - LLR Ecole polytechnique
Class : initialization Class declaration: class AClass { … public: AClass(int); AClass(double); AClass(int, int); … private: int number; const double pi; }; Class implementation: #include “AClass.hh” // could be: AClass::AClass(int i) { number = i; } // or AClass::AClass(int i) : number(i) {;} // here no choice, as const: AClass::AClass(double p) : pi(p) {;} Marc Verderi - LLR Ecole polytechnique
Class : initialization Class declaration: class AClass { … public: AClass(int); AClass(double); AClass(int, int); … private: int number; const double pi; BClass b; }; With only constructor of BClass being with two int as arguments. Class implementation: #include “AClass.hh” // must construct b in all // cases: AClass::AClass(int i) : number(i), b(0,0) {;} // here as well: AClass::AClass(double p) : pi(p), b(0,0) {;} AClass::AClass(int i, int j) : b(i,j) {;} Instructions are executed following the ordering passed after the “:” Note that all members are not initialized properly here ! ;-) Marc Verderi - LLR Ecole polytechnique
Class : operator overloading Class declaration: Syntax for operator overloading cryptic class AClass { … public: // operator “=”: AClass& operator = (const AClass& toCopy); // remember that all operators // can be overloaded, even the // “new” and “delete” ones. … }; Not operator overloading: // Global functions: AClass operator + (const AClass&, const AClass&); At use: #include “AClass.hh” … [some main, method…]{ … AClass toCopy, objA; objA = toCopy; … … AClass objI, objJ, objK; objI = objJ + objK; Marc Verderi - LLR Ecole polytechnique
Inheritance The main feature that makes a language object oriented Marc Verderi - LLR Ecole polytechnique
Inheritance • You define a base class • (base class, interface, abstract interface, etc…) • Specifying what this class should be able to do • and from there derived classes • Which are of the type of the base class • But which specializes it : ie the actual behavior is the one of the derived class Animal: - locomotion() - feeding() Too complicated operations to be described by only a few parameters common to all Animal categories ! HumanBeing:Animal - locomotion() : walk - feeding() : everything Fish:Animal - locomotion() : swim - feeding() : fish,insects Bird:Animal - locomotion() : fly - feeding() : insects Marc Verderi - LLR Ecole polytechnique
Inheritance in Geant4 ? • Used in many places (as it must !) • For example: • Geometry: • G4VSolid: • Abstract interface to describe all geometrical shapes • G4Box, G4Tubs, etc… are derived from G4VSolid • (actually G4VCSGSolid, itself derived from G4VSolid) • Physics: • G4VProcess: • Abstract interface common to all physical processes: • Gamma conversion, multiple scattering, photo-fission, etc… • Sensitivity: • G4VSensitiveDetector, G4VHit, etc… • User interfaces: • Detector construction: G4VUserDetectorConstruction • User actions: G4UserTrackingAction, G4UserSteppingAction,… • … Marc Verderi - LLR Ecole polytechnique
Inheritance in Geant4 ? • Navigation in Geant4 never asks: • distanceToBox if solid is a box • distanceToTubs if solid is a tub • … • But only: • distanceTo the solid • C++ compiler does the rest: • Use method for box if solid is a box, • Use method for tub, if solid is a tub, • … • Makes the navigation generic • If a new solid shape is created, it will be accommodated for free, as inheriting from G4VSolid class. • Used in many places (as it must !) • For example: • Geometry: • G4VSolid: • Abstract interface to describe all geometrical shapes • G4Box, G4Tubs, etc… are derived from G4VSolid • (actually G4VCSGSolid, itself derived from G4VSolid) • Physics: • G4VProcess: • Abstract interface common to all physical processes: • Gamma conversion, multiple scattering, photo-fission, etc… • Sensitivity: • G4VSensitiveDetector, G4VHit, etc… • User interfaces: • Detector construction: G4VUserDetectorConstruction • User actions: G4UserTrackingAction, G4UserSteppingAction,… • … X X X X Marc Verderi - LLR Ecole polytechnique
Inheritance in Geant4 ? • Used in many places (as it must !) • For example: • Geometry: • G4VSolid: • Abstract interface to describe all geometrical shapes • G4Box, G4Tubs, etc… are derived from G4VSolid • (actually G4VCSGSolid, itself derived from G4VSolid) • Physics: • G4VProcess: • Abstract interface common to all physical processes: • Gamma conversion, multiple scattering, photo-fission, etc… • Sensitivity: • G4VSensitiveDetector, G4VHit, etc… • User interfaces: • Detector construction: G4VUserDetectorConstruction • User actions: G4UserTrackingAction, G4UserSteppingAction,… • … Marc Verderi - LLR Ecole polytechnique
Inheritance : the keyword virtual • A class is a « base class/abstract class/… » if at least one of its methods is declared « virtual » • Makes the compiler aware that the code to call is that of the daughter classes • Example in G4UserSteppingAction: virtual void UserSteppingAction(const G4Step*) {;} • In this case, it has a default implementation… • Which does nothing (but in general, can be more than that) • The class is an « interface » • You can create an object of this type in memory: G4UserSteppingAction dummySteppingAction; • Example in G4VUserDetectorConstruction: virtual G4VPhysicalVolume* Construct() = 0; • It is a so-called « pure virtual method »: • It does not propose a default implementation • The class is an « abstract interface » • Creating such an object in memory is not possible • Only pointers on it can be declared: G4VUserDetectorConstruction* detector; Marc Verderi - LLR Ecole polytechnique
Syntax for inheritance • Example of detector construction, in example N03 • In header file G4VUserDetectorConstruction.hh : class G4VUserDetectorConstruction { … public: virtual G4VPhysicalVolume* Construct() = 0; … }; • In header file ExN03DectectorConstruction.hh : class ExN03DectectorConstruction : public G4VUserDetectorConstruction { … public: G4VPhysicalVolume* Construct(); … }; Marc Verderi - LLR Ecole polytechnique
Inheritance: a few more things • Remember about publicity keywords: • “public:” fields are accessible to all • “protected:” • These fields are accessible to daughter classes • “private:”: fields accessible to the class only (and to “friend” classes) • Destructor of a base class is declared virtual • In general, to allow your stuff to be deleted when the destructor of the base class is called • Initialization: • Base class constructor to be called as case “BClass” before • At execution time: • A construction of a daughter class proceeds as follows: • First the constructor of base class is called • Then the constructor of daughter class is called • Automatically Marc Verderi - LLR Ecole polytechnique
Singleton One word about the technique used for the various “managers” in Geant4 Marc Verderi - LLR Ecole polytechnique
Singleton • A singleton is a class for which only one instance can be created in memory • By construction • ie: no choice ! • Technique very useful to gather informations: • Keep track of all volumes created • Of all particles types declared in the simulation • Etc… • Provide a unique entity to which you can ask • What exist as volumes, or particles, etc… • But also, ask to add or remove a volume, a particle,… • Technique makes use of the keyword static • If in a class declaration a data member is declared static, all objects in memory of that class will share the same data member Marc Verderi - LLR Ecole polytechnique
Singleton: an example In G4SDManager.hh: class G4SDManager { public: static G4SDManager* GetSDMpointer(); … private: G4SDManager(); … private: static G4SDManager* fSDManager; … }; In G4SDManager.cc: G4SDManager* G4SDManager::fSDManager = 0; G4SDManager* G4SDManager::GetSDMpointer() { if (!fSDManager) { fSDManager = new G4SDManager(); } return fSDManager; } • Since constructor is private, only the class can create a G4SDManager • Indeed, I lie: in the code it is actually protected, but this is to make things simplier • The static pointer (and thus unique) is initialized to zero. • Then, upon first call to GetSDMpointer(), the unique instance is created: G4SDManager* manager = G4SDManager::GetSDMpointer(); Marc Verderi - LLR Ecole polytechnique
That’s all… Marc Verderi - LLR Ecole polytechnique