2/22/2020 1 PA199 Advanced Game Design Lecture 2 Introduction to C++ Dr. Fotis Liarokapis 28th February 2020 Introduction • C++ improves on many of C’s features • C++ provides object-oriented programming (OOP) • C++ is a superset to C • No ANSI standard exists yet (in 1994) Some C++ Code #ifndef __SEGMENT_HEADER__ #define __SEGMENT_HEADER__ class Point; class Segment { public: Segment(); virtual ~Segment(); private: Point *m_p0, *m_p1; }; #endif // __SEGMENT_HEADER__ Segment.H #include “Segment.H” #include “Point.H” Segment::Segment() { m_p0 = new Point(0, 0); m_p1 = new Point(1, 1); } Segment::~Segment() { delete m_p0; delete m_p1; } Segment.C #include #include “Segment.H” #include Insert header file at this point. Use library header. Header Guards #ifndef __SEGMENT_HEADER__ #define __SEGMENT_HEADER__ // contents of Segment.H //... #endif • To ensure it is safe to include a file more than once. Header Guards #ifndef __SEGMENT_HEADER__ #define __SEGMENT_HEADER__ // contents of segment.H //... #endif • To ensure it is safe to include a file more than once. If this variable is not defined… Define it. End of guarded area. 2/22/2020 2 C++ Single-Line Comments • In C, /* This is a single-line comment. */ • In C++, // This is a single-line comment • But note that compilers will accept both! C++ Stream Input/Output • In C, printf(“Enter new tag: “); scanf(“%d”, &tag); printf(“The new tag is: %d\n”, tag); • In C++, cout << “Enter new tag: “; cin >> tag; cout << “The new tag is : “ << tag << ‘\n’; An Example // Simple stream input/output #include main() { cout << "Enter your age: "; int myAge; cin >> myAge; cout << "Enter your friend's age: "; int friendsAge; cin >> friendsAge; An Example . if (myAge > friendsAge) cout << "You are older.\n"; else if (myAge < friendsAge) cout << "You are younger.\n"; else cout << "You and your friend are the same age.\n"; return 0; } Declarations in C++ • In C++, declarations can be placed anywhere • Except in the condition of a while, do/while, for or if structure • An example cout << “Enter two integers: “; int x, y; cin >> x >> y; cout << “The sum of “ << x << “ and “ << y << “ is “ << x + y << ‘\n’; • Another example for (int i = 0; i <= 5; i++) cout << i << ‘\n’; Data Types in C++ struct Name { char first[10]; char last[10]; }; • In C, • struct Name stdname; • In C++, • Name stdname; • The same is true for enums and unions 2/22/2020 3 Pointers int x = 10; int *p; p = &x; *p = 20; Declares a pointer to an integer & is address operator gets address of x * dereference operator gets value at p Pointers . int x = 10; int *p; p = &x; p gets the address of x in memory. p x10 Pointers .. int x = 10; int *p; p = &x; *p = 20; *p is the value at the address p. p x20 Pointers Example int *intPtr; intPtr = new int; *intPtr = 6837; delete intPtr; int otherVal = 5; intPtr = &otherVal; Create a pointer Allocate memory Set value at given address Change intPtr to point to a new location 6837*intPtr 0x0050intPtr 5*intPtr 0x0054intPtr otherVal &otherVal Deallocate memory Allocating memory using new • Point *p = new Point(5, 5); • new can be thought of a function with slightly strange syntax • new allocates space to hold the object • new calls the object’s constructor • new returns a pointer to that object Deallocating memory using delete // allocate memory Point *p = new Point(5, 5); ... // free the memory delete p; For every call to new, there must be exactly one call to delete 2/22/2020 4 Arrays int intArray[10]; Int Array[0] = 6837; int *intArray; intArray = new int[10]; intArray[0] = 6837; ... delete[] intArray; Stack allocation Heap allocation More Arrays Examples int x = 10; int* nums1 = new int[10]; // ok int* nums2 = new int[x]; // ok • Initializes an array of 10 integers on the heap • C equivalent of int* nums = (int*)malloc(x * sizeof(int)); Multidimensional Arrays int x = 3, y = 4; int* nums3 = new int [x] [4] [5]; // ok int* nums4 = new int [x] [y] [5]; // BAD! • Initializes a multidimensional array • Only the first dimension can be a variable • The rest must be constants • Use single dimension arrays to fake multidimensional ones Strings char myString[20]; strcpy(myString, "Hello World"); myString[0] = 'H'; myString[1] = 'i'; myString[2] = '\0'; printf("%s", myString); A string in C++ is an array of characters Strings are terminated with the NULL or '\0' character output: Hi Parameter Passing int add(int a, int b) { return a+b; } int a, b, sum; sum = add(a, b); Pass by value int add(int *a, int *b) { return *a + *b; } int a, b, sum; sum = add(&a, &b); Pass by reference Make a local copy of a and b Pass pointers that reference a and b. Changes made to a or b will be reflected outside the add routine Parameter Passing . int add(int &a, int &b) { return a+b; } int a, b, sum; sum = add(a, b); Pass by reference – alternate notation 2/22/2020 5 Class Basics #ifndef _IMAGE_H_ #define _IMAGE_H_ #include #include "vectors.h“ class Image { public: ... private: ... }; #endif Include a library file Include a local file Prevents multiple references Variables and functions accessible from anywhere Variables and functions accessible only from within this class’s functions Creating an instance Image myImage; myImage.SetAllPixels(ClearColor); Image *imagePtr; imagePtr = new Image(); imagePtr->SetAllPixels(ClearColor); ... delete imagePtr; Stack allocation Heap allocation Organizational Strategy image.h Header file: Class definition & function prototypes .C file: Full function definitions Main code: Function references image.C main.C void SetAllPixels(const Vec3f &color); void Image::SetAllPixels(const Vec3f &color) { for (int i = 0; i < width*height; i++) data[i] = color; } myImage.SetAllPixels(clearColor); Constructors & Destructors class Image { public: Image(void) { width = height = 0; data = NULL; } ~Image(void) { if (data != NULL) delete[] data; } int width; int height; Vec3f *data; }; Constructor: Called whenever a new instance is created Destructor: Called whenever an instance is deleted Constructors Specifics Image(int w, int h) { width = w; height = h; data = new Vec3f[w*h]; } Constructors can also take parameters Image myImage = Image(10, 10); Image *imagePtr; imagePtr = new Image(10, 10); Using this constructor with stack or heap allocation: stack allocation heap allocation The Copy Constructor Image(Image *img) { width = img->width; height = img->height; data = new Vec3f[width*height]; for (int i=0; idata[i]; } Image(Image *img) { width = img->width; height = img->height; data = img->data; } A default copy constructor is created automatically, but it is often not what you want: 2/22/2020 6 Destructors Specifics • Delete calls the object’s destructor • Delete frees space occupied by the object • A destructor cleans up after the object • Releases resources such as memory Destructors – An Example class Segment { public: Segment(); virtual ~Segment(); private: Point *m_p0, *m_p1; }; Destructors – An Example . Segment::Segment() { m_p0 = new Point(0, 0); m_p1 = new Point(1, 1); } Segment::~Segment() { delete m_p0; delete m_p1; } Syntactic Sugar “->” Point *p = new Point(5, 5); // Access a member function: (*p).move(10, 10); // Or more simply: p->move(10, 10); Passing Classes as Parameters bool IsImageGreen(Image img); If a class instance is passed by value, the copy constructor will be used to make a copy Computationally expensive bool IsImageGreen(Image *img); It’s much faster to pass by reference: bool IsImageGreen(Image &img); or Class Hierarchy class Object3D { Vec3f color; }; class Sphere : public Object3D { float radius; }; class Cone : public Object3D { float base; float height; }; Child classes inherit parent attributes Object3D Sphere Cone 2/22/2020 7 Class Hierarchy . Sphere::Sphere() : Object3D() { radius = 1.0; } Child classes can call parent functions Child classes can override parent functions class Object3D { virtual void setDefaults(void) { color = RED; } }; class Sphere : public Object3D { void setDefaults(void) { color = BLUE; radius = 1.0 } }; Call the parent constructor SuperclassSubclass Introducing const void Math::printSquare(const int& i) { i = i*i; cout << i << endl; } int main() { int i = 5; Math::printSquare(i); Math::printCube(i); } Summary with Header File begin header guard #ifndef __SEGMENT_HEADER__ #define __SEGMENT_HEADER__ class Point; class Segment { public: Segment(); virtual ~Segment(); private: Point *m_p0, *m_p1; }; #endif // __SEGMENT_HEADER__ Segment.Hheader file forward declaration class declaration constructor destructor end header guard member variables need semi-colon Can also pass pointers to const void Math::printSquare(const int* pi) { *pi = (*pi) * (*pi); cout << i << endl; } int main() { int i = 5; Math::printSquare(&i); Math::printCube(&i); } Declaring things const const River nile; const River* nilePc; River* const nileCp; const River* const nileCpc Read pointer declarations right to left // A const River const River nile; // A pointer to a const River const River* nilePc; // A const pointer to a River River* const nileCp; // A const pointer to a const River const River* const nileCpc 2/22/2020 8 Inheritance #include “Segment.H” class DottedSegment : public Segment { // DottedSegment declaration }; must include parent header file DottedSegment publicly inherits from Segment Virtual • In Java every method invocation is dynamically bound, meaning for every method invocation the program checks if a sub-class has overridden the method • You can override this (somewhat) by using the keyword “final” in Java • In C++ you have to declare the method virtual if you want this functionality • So, “virtual” is the same thing as “not final” • Just like you rarely say things are final in Java, you should rarely not say things are virtual in C++ Virtual Functions in C++ class Object3D { virtual void intersect(Ray *r, Hit *h); }; class Sphere : public Object3D { virtual void intersect(Ray *r, Hit *h); }; myObject->intersect(ray, hit); If a superclass has virtual functions, the correct subclass version will automatically be selected Sphere *mySphere = new Sphere(); Object3D *myObject = mySphere; A superclass pointer can reference a subclass object Actually calls Sphere::intersect SuperclassSubclass Pure Virtual Functions class Object3D { virtual void intersect(Ray *r, Hit *h) = 0; }; A pure virtual function has a prototype, but no definition. Used when a default implementation does not make sense A class with a pure virtual function is called a pure virtual class and cannot be instantiated However, its subclasses can The main function int main(int argc, char** argv); This is where your code begins execution Number of arguments Array of strings argv[0] is the program name argv[1] through argv[argc-1] are command-line input Coding tips #define PI 3.14159265 #define MAX_ARRAY_SIZE 20 Use the #define compiler directive for constants printf("value: %d, %f\n", myInt, myFloat); cout << "value:" << myInt << ", " << myFloat << endl; Use the printf or cout functions for output and debugging assert(denominator != 0); quotient = numerator/denominator; Use the assert function to test “always true” conditions 2/22/2020 9 Coding tips . delete myObject; myObject = NULL; After you delete an object, also set its value to NULL (This is not done for you automatically) This will make it easier to debug memory allocation errors assert(myObject != NULL); myObject->setColor(RED); Segmentation Faults int intArray[10]; intArray[10] = 6837; Image *img; img->SetAllPixels(ClearColor); Typical causes: Access outside of array bounds Attempt to access a NULL or previously deleted pointer These errors are often very difficult to catch and can cause erratic, unpredictable behavior Common Pitfalls void setToRed(Vec3f v) { v = RED; } Since v is passed by value, it will not get updated outside of The set function The fix: void setToRed(Vec3f &v) { v = RED; } void setToRed(Vec3f *v) { *v = RED; } or Common Pitfalls .. Sphere* getRedSphere() { Sphere s = Sphere(1.0); s.setColor(RED); return &s; } C++ automatically deallocates stack memory when the function exits, so the returned pointer is invalid The fix: Sphere* getRedSphere() { Sphere *s = new Sphere(1.0); s->setColor(RED); return s; } It will then be your responsibility to delete the Sphere object later Advanced topics • Lots of advanced topics, but a few will be required for this course • friend or protected class members • inline functions • static functions and variables • operator overloading • compiler directives Some Useful Links • C++ Programming • http://www.syvum.com/squizzes/cpp/ • Online C/C++ Documentation • http://www.thefreecountry.com/documentation/onlinecpp.s html • C++ Language Tutorials • http://www.cs.wustl.edu/~schmidt/C++/ • The C++ Programming Language • http://www.research.att.com/~bs/C++.html 2/22/2020 10 Questions