.. highlight:: c++ :linenothreshold: 5 ************************** Objects and Classes in C++ ************************** Concepts ======== General Object-oriented Programming ----------------------------------- :object: a collection of coherent states and behaviors :class: a template of a group of similar objects :state: data, property, attribute, member variable :behavior: method, member function map to C++ concepts ------------------- :class: a type :object: a variable (instance) of a class type :state: an instance variable :behavior: a method .. code-block:: C++ :caption: A simple class class Point { int x; // an instance variable int y; // above: members are private by default public: // below: members are public // below are all methods Point(); // default constructor Point(int x, int y); void setX(int x); // mutator/setter int getX() { // accessor/getter, inline definition return x; } void setY(int y); // mutator/setter int getY(); }; // end with ; // out-of-line definition after Point::Point(): x(0), y(0) {} Point::Point(int x, int y): x(x), y(y) {} void Point::setX(int x) { this->x = x; } void Point::setY(int y) { this->y = y; } int Point::getY() { return y;} Class Declaration ================= + class keyword (or struct keyword) + Usually in header file + Semicolon after } + Members * data member - instance variable * function member - method (member function) + visibility (access specifier) * as sections (different from Java) - public: accessible anywhere - private: accessible only within objects of the same class - protected, etc.: not discussed in the courses * default - private in class - public in struct * always prefer information hiding - make private if possible - almost all instance variables are private - only methods to be used out of the class should be public Methods ======= + Inline definitions: in the class declaration + Out-of-line definitions: out of the class declaration * Scope resolution operator ``::`` to specify the owner of the method (the class) * ``this`` pointer as a pointer pointing to the current object in method definition - use of ``->`` operator + Types of methods .. glossary:: Constructor The methods to be triggered when the object is created. Same name as the class. No return type (because they always return the new object). May be overloaded. Destructor The method to be triggered when the object is destroyed. No parameter. One per class. Accessor A.k.a getter. A simple method to return the value of an instance variable. Should be const methods in most cases. Mutator A.k.a setter. Takes one const parameter and set an instance variable to the value passed in. Private helper A general name of all private methods as they are usually used to *help* other methods. + Constructor * No return type * Initializer list (read :ref:`this `) - constructor only syntax - initializes values of instance variables * Default constructor - no parameter - define initial value - to trigger :: MyClass obj; MyClass obj(); MyClass obj{}; MyClass obj[10]; // every element created using the default constructor * Parameterized constructor * Duplication constructors (further discussed :doc:`here `) - copy constructor - move constructor + Const methods: methods that cannot not modify any instance variable * **any other method called within a const method must be const too** :: class MyClass { int size; public: void print() const { cout << "Hello!\n"; } int size() const { return size; } }; .. _data-init: Data Initialization of Non-Static Instance Variable =================================================== #. In-class initializer (constructor only syntax, since c++11) #. Initializer list in the constructor (preferred) #. Assignment in the constructor .. note:: Two methods can be mixed. Use the first method for initial values shared among multiple constructors; Use the second method for values that differs among various constructors. When used together, the first will be ignored. :: // 1. in-class initializer, always effective class MyClass { private: int value = 10; // <-- here public: MyClass()=default; // doing nothing }; // 2. constructor member initializer list, only affect one constructor class MyClass { private: int value; public: MyClass(): value(10) {} // <-- here }; // 3. Naive assignment class MyClass { private: int value; public: MyClass() { value = 10; // <-- here } }; Using Class/Object ================== + Declare a variable of a class type * Initialization using the constructor:: MyClass myObj1(10); MyClass myObj1 = 10; // same as the above example MyClass myObj1{10}; // since C++11 * Disposable object assignment (Class name followed by parenthesis to trigger the constructor):: int myFunction(MyClass obj); int main() { // as a parameter, MyClass(10) is a temp object cout << myFunction(MyClass(10)) << endl; // assign to another object // copy constructor or copy assignment operator will be triggered // MyClass(10) is a temp object MyClass objArray[10]; // object array, default constructor triggered objArray[0] = MyClass(10); // copy assignment operator triggered } + ``.`` member accessing operator:: MyClass obj; cout << obj.getValue() << endl; + ``->`` member accessing operator from pointer:: // pointer to class MyClass *objPtr; objPtr = new MyClass; // objPtr->getValue() is same as (*objPtr).getValue() cout << objPtr->getValue() << endl; + ``::`` Domain resolution operator:: // Name space std::string myString; // Class method out-of-line definition void MyClass::print() { cout << "value: " << this->value << endl; } // Class static members // static int square(int value) { return value * value}; MyClass obj1; cout << obj1.square(5) << endl; // use object to access cout << MyClass::square(5) << endl; // use class to access UML Class Diagrams (FYI) ======================== The Unified Modeling Language is a general-purpose modeling language used in software engineering. The class diagram is one type of UML diagram used to model classes and relationships among them in object-oriented programming. The class diagrams used here is in the PlantUML format. You can check this `document`__ for more information. .. __: https://plantuml.com/class-diagram#3644720244dd6c6a .. image:: http://www.plantuml.com/plantuml/png/SoWkIImgAStDuL9GICv9B2vM22rEBLAe1d9rYqkAClFI5J9Ja3XvYRcfGAusI9M69fm5LwgZWAGGB0_bfwUM-065DD34F5t08hLS3gbvAK1d0000 :width: 300 :alt: Example: User Class .. code-block:: class User { -string id -string name +User() +User(string id, string name) +string getName() +string getID() } Static Members (FYI) ==================== + static keyword + one per class + global life span + stored in the ``static`` memory region + instance variable * data shared among objects * can only be initialized outside of the class declaration:: // my-class.hpp class MyClass { private: static int count; // NEVER initialize here! public: // ... }; // my-class.cpp // omit the static keyword int MyClass::count = 10; + method * can not access any instance variable * can access static instance variable * e.g. pure math functions * either ``MyClass::method()`` or ``obj.method()`` to trigger Class Example ============= .. code-block:: c++ :caption: my-class.hpp #ifndef MY_CLASS_HPP #define MY_CLASS_HPP class MyClass { private: // optional, anything not in the public section is private int value; void doubleVal(); // private helper public: MyClass(); // default constructor MyClass(int value); // parameterized constructor int getValue() const; // accessor/getter void setValue(int value); // mutator/setter int getDoubledValue(); // general public method }; // WARNING: must have ; here #endif // MY_CLASS_HPP .. code-block:: c++ :caption: my-class.cpp #include "my-class.hpp" void MyClass::doubleVal() { value *= 2; } int MyClass::getDoubledValue() { doubleVal(); return value; } // default constructor // with initializer list to set value to 0 MyClass::MyClass(): value(0) {} // parameterized constructor // using initializer list // MyClass::MyClass(int value): value(value) {} // not using initializer list MyClass::MyClass(int value) { // this->value refers to the instance variable // must add this-> when names conflict this->value = value; } int MyClass::getValue() const { return value; } // cannot use the initializer list because this is not a constructor void MyClass::setValue(int value) { this->value = value; } .. code-block:: c++ :caption: main.cpp // pay attention to the order // user header first // system header last #include "my-class.hpp" #include using namespace std; int main() { // trigger the default constructor MyClass obj1; cout << obj1.getValue() << endl; // get 0 // trigger the parameterized constructor MyClass obj2(10); // alternatives // MyClass obj2{10}; // since c++11, preferred // MyClass obj2 = 10; // trigger the parameterized constructor cout << obj2.getValue() << endl; // get 10 MyClass *ptr1; ptr1 = new MyClass(15); // use new to call the constructor cout << ptr1->getValue() << endl; // get 15 cout << (*ptr1).getValue() << endl; // get 15 } .. code-block:: makefile :caption: makefile main: main.o my-class.o g++ -o $@ $^ main.o: main.cpp my-class.hpp g++ -std=c++14 -Wall -c -o $@ $< my-class.o: my-class.cpp my-class.hpp g++ -std=c++14 -Wall -c -o $@ $< clean: rm -f *.o main