Code Notes: Introduction to C++, part 1

Topics covered: const keyword; passing objects through functions

Link to source code: http://www.cs.tufts.edu/comp/15/examples/CPP/ex1.cpp

#include <iostream>

using namespace std; 

/*

Object: a repository of data. E.g. if myList is a GroceryList object, 
	myList can record my grocery list.

Class: a type of object. Many objects of the same class can exist. 
	E.g. myList and yourList may both be GroceryList objects. 
	Of course, there could be different objects belonging to 
	different classes. A ToDoList class type contains different 
	kinds of data than a GroceryList class.

Method (or Member function): operates on an object or a class. 
	A method is associated with a particular class. 
	E.g. addItem can be a member function that adds an item to 
	any GroceryList object.

Inheritance: A class may inherit properties from a more general class. 
	E.g. the GroceryList class can inherit from a List class the 
	property of storing a sequence of items.

Polymorphism: is the ability to have one member function call to work 
	on several different classes of objects, even if those classes 
	need different implementations of the member functions. 
	E.g. we can call addItem on every kind of List, but adding an 
	item to the GroceryList is functionally different from adding 
	an item to the ToDoList.

Object-oriented: Each object knows its own class and which member 
	functions manipulate objects belonging to that class. 
	Each GroceryList and each ToDoList knows which implementation 
	of addItem applies to it.

Key aspect that distinguishes object-oriented languages from 
	procedural languages (like C, Fortran, Pascal):
	POLYMORPHISM

 */



/*
1. const keyword

==> "readonly" (different from being a "constant")

*/

void defineConst()
{
  // const double g = 9.8;
  // can also be preferrably written as:
  double const g = 9.8;

  // Here 9.8 is constant; g is a const (read-only variable)
  // replaces:
  // #define g 9.8
  // which does not have a scope
  cout << "g = " << g << endl;
}


/*

2. How to pass an "object" through a function interface

*/

class A
{
public:
  void setx(int val) { x = val; }
  int getx() { return x; }
private:
  int x;
};


// Pass by value
// Actual parameter is copied to the formal parameter by 
// invoking the copy constructor for a
// --> Costly
// --> Safe
void func1(A a)
{
  cout << "x before = " << a.getx() << endl;
  a.setx(6);
  cout << "x after = " << a.getx() << endl;
}

// a is a pointer to object A
// --> Cheap
// --> Not safe
// --> nullptr can be passed
void func2(A* a)
{
  // C++11
  if (a != nullptr) cout << "a is not NULL" << endl;
  a->setx(6);
}

// a is a pointer to const A
// --> Cheap
// --> Safe
// --> nullptr can be passed
// void func3(A const * a)
// {
//   a->setx(6);
// }

// a is a reference to A
// --> Cheap
// --> Not safe
// --> nullptr cannot be passed
void func4(A& a)
{
  a.setx(6);
}

// a is a reference to const A
// --> Cheap
// --> Safe
// --> nullptr cannot be passed
// void func5(A const & a)
// {
//   a.setx(6);
// }

// a is a const pointer to A
// --> Cheap
// --> Pointer is safe; underlying data is not
// --> nullptr can be passed
void func6(A * const a)
{
  a->setx(6);
}

// Note about const:
// const is a property of the path, not of the underlying data

int main()
{
  A a1;
  
  a1.setx(5);
  func1(a1);
  cout << "a1.x = " << a1.getx() << endl;

  a1.setx(5);
  func2(&a1);
  cout << "a1.x = " << a1.getx() << endl;

  a1.setx(5);
  func4(a1);
  cout << "a1.x = " << a1.getx() << endl;

  a1.setx(5);
  func6(&a1);
  cout << "a1.x = " << a1.getx() << endl;
  
  return 0;
}