140 likes | 228 Views
CS 294-73 (CCN 27241) Software Engineering for Scientific Computing http://www.cs.berkeley.edu/ ~colella/CS294 Lecture 5: C++ Key Concepts. Objects in C++. int a, b , c ; FooBar tr ; FooBar & m = tr ; FooBar * p = & tr ; FooBar v[10]; m = v[5]; p = v ; m =p[3];
E N D
CS 294-73 (CCN 27241)Software Engineering for Scientific Computinghttp://www.cs.berkeley.edu/~colella/CS294Lecture 5: C++ Key Concepts
Objects in C++ • int a, b, c; • FooBartr; • FooBar& m = tr; • FooBar* p = &tr; • FooBar v[10]; • m = v[5]; • p=v; • m=p[3]; • p++; p++; // OK • m++; //uh, would this work ? see later for how this might work • m=p[3]; // what element of v is this pointing to now ? • FooBar* v2 = new FooBar[5]; • FooBar* v3 = malloc(5*sizeof(FooBar)); // how are v3 and v2 different?
Functions in C++ • Declaration (also called a prototype) double extractNorm(inta_el, double[3]& a_vec, MaxFactora_ele); • We are telling the compiler: • There will be a function with the name extractNorm which • takes three arguments: an int, a reference to a trilplet of double precision numbers, and an object of type MaxFactor. • on completion will return a double precision floating point number. • Declarations go into a header file. • Header files will have the file extension .h or .H
Source file littleFile.cpp double extractNorm(inta_el, double a_vec[3], MaxFactora_ele); boolrightQuadrant(double a_vex[3], MaxFactora_blink) { if(extractNorm(1,vex, blink)>0) return true; return false; } >g++ -clittleFile.cpp littleFile.cpp:3: error: ‘MaxFactor’ has not been declared littleFile.cpp:4: error: ‘MaxFactor’ has not been declared
littleFile.cpp but a bit better enumMaxFactor {LEFT, RIGHT, STRAIGHT}; intHowAboutAnIntRightHere=5; double extractNorm(int a, double vec[3], MaxFactorele); boolrightQuadrant(double vex[3], MaxFactor blink) { if(extractNorm(1,vex, blink)>0) return true; return false; } >g++ -clittleFile.cpp ; ls littleFile.o • So, what is in this file we just made ?
Let’s look at an object file >file littleFile.o; nm littleFile.o littleFile.o: Mach-O 64-bit object x86_64 0000000000000050 s EH_frame1 0000000000000048 D _HowAboutAnIntRightHere U__Z11extractNormiPd9MaxFactor 0000000000000000 T__Z13rightQuadrantPd9MaxFactor 0000000000000070 S__Z13rightQuadrantPd9MaxFactor.eh D: data segment U: undefined T text segment S: symbol So, what is different about extractNorm and rightQuadrant ?
Trivial example class Counter { private: intm_MyCounter ; intm_zeroEncounters; public: //null constructor Counter():m_MyCounter(0),m_zeroCrossings(0) {} void incrementCounter() { if(m_MyCounter==-1) m_zeroEncounters++; m_MyCounter++; } void decrementCounter() { if(m_MyCounter==1) m_zeroEncounters++; m_MyCounter--; } virtual intgetCounterValue() { return m_MyCounter; } const }; • The object has it’s data m_MyCounterm_zeroEncounters. • Mostly data members are made private. Can you guess why ? • This class has a public interface, what a user of Counter would want to be able to do with this object. Is This useful yet ?
Object-Oriented Programming • Abstractions in programming are often described in terms of data, and functions that operate on that data. • So, put them together in the language • Several languages have adopted this paradigm • C++, Java, Python, F90, C#, Modula-2 • Some had it from the start, some found a way to make it work • You can do OOP in any language, just some make it easier • The main benefits that makes bundling the two ideas together desirable. • Encapsulation • Modularity • Inheritance • Primary object in C++ is the class
Encapsulation • Hiding the internals of the object protects its integrity by preventing users from setting the internal data of the component into an invalid or inconsistent state. • In Counter, how might a public data access result in an inconsistent state ? • A benefit of encapsulation is that it can reduce system complexity, and thus increases robustness, by allowing the developer to limit the interdependencies between software components. • The code presents a contract for the programmer • If private data has gotten messed up, you don’t have to look over your whole code base to determine where the mistake occurred. • The compiler has enforced this contract for you. • Except when you use ‘friend’ declarations. • Sleeping with friends is sleeping with every one of their friends.
Modularity • Separation of Concerns • There is a small number of people that need to know how LevelFluxRegister is implemented. • There are a dozen people that need to know to use this class • There are several dozen people that just need to know this class is doing it’s job. • Improve maintainability by enforcing logical boundaries between components. • Modules are typically incorporated into the program through interfaces. • C++ makes this explicit with the public interface
Inheritance “is a” • One of two primary methods of abstraction in C++ (the other being templates) • ‘is-a’ vs ‘has-a’ • inheriting from an object is telling a person that this object ‘is-a’ another object • ‘has-a’ is done in C++ by giving a class a member data member • numerous failings in class design come from confusing these ideas. • Imagine thinking of Counter as an ‘is-a’ relationship…. • Good rule of thumb: • Does EVERY member function of the base class make sense for the derived class ? • How about an example
Simple Inheritance class MonitoredCounter : public Counter { private: intm_accessCount; public: MonitoredCounter():m_accessCount(0) {} virtual intgetCounterValue() { m_accessCount++; return Counter::getCounterValue(); } virtual intaccessCount(){returnm_accessCount;} }; • What compiler errors will occur if I try to compile this .cpp file ? • Have we satisfied our rule of thumb for an ‘is-a’ relationship?
Simple Inheritance with fixes! #ifndef MONITOREDCOUNTER_H #define MONITOREDCOUNTER_H #include “Counter.H” #include “NamespaceHeader.H” class MonitoredCounter : public Counter { private: mutableintm_accessCount; public: MonitoredCounter():m_accessCount(0) {} virtual intgetCounterValue() { m_accessCount++; return Counter::getCounterValue();} const virtual intaccessCount(){returnm_accessCount;} const }; #include “NamespaceFooter.H #endif
Constructors are special • What happens when I declare a new MonitoredCounter object ? #include “MonitoredCounter.H” intmain(intargc, char* argv[]) { MonitoredCounter c1, c2[2]; intcheckValue = c1.getCounterValue(); checkValue = c2[0].getCounterValue(); inthowBig = sizeof(MonitoredCounter); // care to guess? return checkValue; } Compiler will build a .o file • make room on the stack for one int and one char* object • make room on the stack, using the D declaration, for three MonitoredCounter objects and two int object. • Call the inheritance tree of constructor objects • call Counter’s null constructor, then MonitoredCounter’s null constructor