Pointers are just values that indicate memory addresses and the type of data that the programmer thinks is there.
Suppose bptr is a pointer to a structure:
struct MyBalls_s * bptr;
Then I could access the fields in the structure like this:
(*bptr).x = (*bptr).x + (*bptr).u * dt;
The -> operator is "syntactic sugar" to make this prettier:
bptr->x = bptr->x + bptr->u * dt;
If f is a function, then &f is a pointer to its address. Example:
#include <iostream> double square(double x) { return x*x; } double cube(double x) { return x*square(x); } int main() { using namespace std; double (*fptr)(double); // fptr declared as type "double (*)(double)" double t=5.0; fptr= □ // note no () cout << "square of " << t << " is " << (*fptr)(t) << "\n"; fptr= &cube; cout << "cube of " << t << " is " << (*fptr)(t) << "\n"; }
C++ | C |
struct MyStruct_s { int i; void set_i(int ii); }; void test() { struct MyStruct_s s; s.set_i(42); } |
struct MyStruct_s { int i; }; void MyStruct_set_i(int ii); void test() { struct MyStruct_s s; MyStruct_set_i(&s, 42); } |
C++ | C |
struct MyStruct_s { int i; virtual void set_i(int ii); }; void test() { struct MyStruct_s s; s.set_i(42); } |
struct MyStruct_s { int i; void (*set_i)(int ii); }; void test() { struct MyStruct_s s; (*(s.set_i))(42); } |
The above example is just to give you the idea, and is slightly incomplete because I omitted the initialization of the function pointer, and because I don't use a "virtual function table" like most C++ compilers.
This is just like a struct with the addition of public, protected and private flags for the members:
class MyClass { private: int i; public: virtual void set_i(int ii); }; void test() { MyClass c; c.set_i(42); // OK c.i= 45; // compile-time error }
A constructor is a function that automatically gets run each time a variable of a particular class type is made. It has the same name as the class, and doesn't have a declared type, not even void.
A destructor is a function that automatically runs each time a variable of class type is deleted, e.g., when the block of code in which it was made ends.
class MyClass { public: MyClass(); // constructor MyClass(int i); // constructor with 1 argument ~MyClass(); // destructor }
Sometimes you don't know in advance how many objects will need to make. (E.g., if the number of balls can be specified by the user at run time.) A vector is one way of handling this. Another way is the new operator:
MyClass *cptr1; MyClass *cptr2; cptr1= new MyClass; // runs default constructor cptr2= new MyClass(42); // runs constructor with 1 int argument
This allocates memory for the new object and runs the constructor.
You have to explicitly free the memory when you're done with it:
delete cptr1;
API: Application Programming Interface
Compilation recipes:
VC:
C:\ROOT\BIN\thisroot.bat set INCLUDE=%INCLUDE%;%ROOTSYS%\include cl /EHsc (filename.cc) C:\ROOT\LIB\lib*.lib
GCC (linux):
source /path-to-root/bin/thisroot.sh g++ `root-config --cflags --libs` (filename.cc) -o exename
The ROOT API is too complicated to summarize in class, although the documentation is not bad.
There is a link to an example application on the course web page.
[ROOT] | http://root.cern.ch/ |