C++ Review User Defined Types • Built-in data types are simple. Specific problems may demand aggregate/more complex data types. – Ex: polygons, matrices, car specifications, etc… • Types define both data and operations that can be performed on that data – Ex: vectors might store x,y coordinates and have addition/subtraction operations • C++ allows for complex types in the form of classes and structs Class Example struct Point { float m_x, m_y; void Set ( float x, float y ) { m_x = x; m_y = y; } }; class Point { float m_x, m_y; public: void Set ( float x, float y ) { m_x = x; m_y = y; } }; In C++, the only difference between struct/class is public/private scope Public, Protected, Private Scopes • Public: functions/data that any part of a program may access – Ex: Data Accessors – GetData(), modifiers – SetData(newData), operations – ActionX() • Protected: functions/data that only the class and any derived subclasses may access – Ex: Helper functions for operations. Most data in class hierarchies • Private: functions/data that only the class itself may access – Ex: Helper functions and some data Encapsulation • A mechanism for restricting access to some of the object's components • Advice: – Helper functions and data should be “Encapsulated”, i.e., should be private or protected – Use Accessors/Modifiers to “Get”/“Set” the data Constructors and Destructors • Constructors – “functions” that define how data is initialized – Same name as the class itself – Default constructor – takes no parameters, e.g., Point() – Copy constructor – takes an object of the class itself to initialize the data, e.g., Point(oldPoint) • Destructors – define how data is deleted – Same name as the class except with a ~, e.g., ~MyClass() – Usually not called in code you write. The compiler automatically calls it when an object is deleted. Abstract Types and Hierarchies • Often many types have things in common, e.g., all shapes can be drawn or all shapes have color • However, you cannot concretely define a shape. In this case a shape is abstract • We derive more concrete classes off of abstract ones, e.g., a circle is a concrete shape Inheritance • Inheritance allows reuse of code in existing objects and definition of subtypes Shape Circle Square Triangle Inheritance • Inheritance allows reuse of code in existing objects and definition of subtypes Base class: class that is inherited from Shape Circle Square Triangle Inheritance • Inheritance allows reuse of code in existing objects and definition of subtypes Derived class: class that does the inheriting Shape Circle Square Triangle Inheritance • Inheritance allows reuse of code in existing objects and definition of subtypes Derived class: class that does the inheriting Shape Circle Square Triangle • Derived classes have access to public/protected data and functions of the base class Inheritance Example class Shape { protected: Color m_c; public: Shape(Color c) : m_c(c) {} class Circle : public Shape { float m_radius; public: Circle(Color c, float r) : Shape(c), m_radius(r) {} void Draw() {/*do nothing*/} }; void Draw() {/*draw circle of radius r*/} }; class Square : public Shape { float m_side; public: Square(Color c, float s) : Shape(c), m_side(s) {} void Draw() {/*draw circle of radius r*/} }; Virtual Functions • Function whose behavior can be overridden in a derived class. • A call to a virtual function will call the function of the original object regardless of the type of the pointer. class Shape { protected: Color m_c; public: Shape(Color c) : m_c(c) {} // pure virtual function virtual void Draw() = 0; }; class Circle : public Shape { float m_radius; public: Circle(Color c, float r) : Shape(c), m_radius(r) {} virtual void Draw() {/*draw circle of radius r*/} }; Virtual Functions • Function whose behavior can be overridden in a derived class. • A call to a virtual function will call the function of the original object regardless of the type of the pointer. class Shape { protected: Color m_c; public: Shape(Color c) : m_c(c) {} // pure virtual function virtual void Draw() = 0; }; class Circle : public Shape { float m_radius; public: Circle(Color c, float r) : Shape(c), m_radius(r) {} virtual void Draw() {/*draw circle of radius r*/} }; Requires derived classes to implement this function. Virtual Functions • Function whose behavior can be overridden in a derived class. • A call to a virtual function will call the function of the original object regardless of the type of the pointer. class Shape { protected: Color m_c; public: Shape(Color c) : m_c(c) {} // pure virtual function virtual void Draw() = 0; }; class Circle : public Shape { float m_radius; public: Circle(Color c, float r) : Shape(c), m_radius(r) {} virtual void Draw() {/*draw circle of radius r*/} }; Classes with pure virtual functions are abstract and cannot be instantiated. Virtual Functions • Function whose behavior can be overridden in a derived class. • A call to a virtual function will call the function of the original object regardless of the type of the pointer. class Shape { protected: Color m_c; public: Shape(Color c) : m_c(c) {} // pure virtual function virtual void Draw() = 0; }; class Circle : public Shape { float m_radius; public: Circle(Color c, float r) : Shape(c), m_radius(r) {} virtual void Draw() {/*draw circle of radius r*/} }; Shape *s = new Circle ( Red, 1.0f ); s->Draw ( ); // calls Circle:Draw ( ) Virtual Functions • Function whose behavior can be overridden in a derived class. • A call to a virtual function will call the function of the original object regardless of the type of the pointer. class Shape { protected: Color m_c; public: Shape(Color c) : m_c(c) {} class Circle : public Shape { float m_radius; public: Circle(Color c, float r) : Shape(c), m_radius(r) {} void Draw() {/*do nothing*/} virtual void Draw() {/*draw circle of radius r*/} }; }; Shape *s = new Circle ( Red, 1.0f ); s->Draw ( ); // calls Shape:Draw ( ) Operator Overloading • Operator overloading provides a way to use common operators with user defined types – Ex: assignment (=), addition (+), input (>>) class MyClass{ private: string m_name; public: MyClass(string name) : m_name(name) {} MyClass& operator=(const MyClass& m) { m_name = m.m_name; } }; Exercises 1. Create a struct called Point. This will be a 2D point. Provide a constructor, overloaded assignment operator, and public data. 2. Create an abstract class called Shape. Shape will have protected data of a Point describing the location of the shape and a pure virtual function Print(). 3. Create subclasses of Shape, Circle and Square with private data. Overload the print function to print out the type and data members of the class. For example, Circle::Print () might output “Circle at position 3,5 with radius 2”. 4. Create a main function instantiating a Square and a Circle as an abstract Shape. Call the virtual function of Shape.