James (Siyuan) Guo     Home | CV | Research | Notes | Projects | Teaching | Blogs | Contact



Basic C++ Notes

C++ Structures:

C++ Comparing with C:

C++ special features:

C++ inheriting C:

C++ Compiler:

C++ programming files:

// rectangle.h:  
// include lines like this at the top; change the all-caps
// name to match the file name, rectangle.h in this case

#ifndef RECTANGLE_H  

#define RECTANGLE_H

class Rectangle { // structure
	private:
	int height;
	int width;
	public:
	Rectangle(int h = 0, int w = 0) : height(h), width(w) { };
	int get_height();
	int get_width();
};

// include this line at the bottom

#endif

Makefile in C++:


# Makefile:

CC=g++  
CFLAGS=-std=c++11 -pedantic -Wall -Wextra

main: mainFile.o functions.o  
	$(CC) -o main mainFile.o functions.o

mainFile.o: mainFile.cpp functions.h
	$(CC) $(CFLAGS) -c mainFile.cpp

functions.o: functions.cpp functions.h
	$(CC) $(CFLAGS) -c functions.cpp

clean:  
	rm -f *.o main

enum type:

enum Foo { a, b, c = 10, d, e = 1, f, g = f + c };
//a = 0, b = 1, c = 10, d = 11, e = 1, f = 2, g = 12
enum color : char { red, yellow, green = 20, blue };
color col = red;  
char n = blue; // n == 21
enum class Color { red, yellow, blue };  
enum class MyColor { myblue, myyellow, myred };  
Color col = Color::red;  
if (col == MyColor::myred) { // Compiler will give an error.
	// ...
}

lambdas functions:


#include <iostream>

#include <cstdlib>
template <typename T>
int compare_T (const void *v1, const void *v2) {
	if (*(const T*)v1 < *(const T*)v2) return -1;
	else if (*(const T*)v2 < *(const T*)v1) return 1;
	else return 0;
}

template <typename T>
void my_qsort(T *values, size_t count, int (*cmp)(const void *, const void *)) {
	// the variable cmp is the functor used ^^^^ as a function input.
	qsort(values, count, sizeof(T), cmp);
}

int main( void ) {
	int v[12];
	size_t sz = sizeof(v) / sizeof(int);  
	for (unsigned int i = 0; i < sz; i++) v[i] = rand()%100;
	for (unsigned int i = 0; i < sz; i++ ) {
		std::cout << " " << v[i] ; std::cout << std::endl;
	}
	my_qsort(v, sz, compare_T<int>);
	// the function ^^^^^^^^^^^^^^ is passed as a functor variable.
	for (unsigned int i = 0; i < sz ; i++) {
		std::cout << " " << v[i] ; std::cout << std::endl;
	}
	return 0;
}

auto keyword:


#include <iostream>

#include <cstdlib>

template <typename T, typename T_cmp>
void my_qsort(T *values, size_t count, T_cmp cmp) {
	// the variable cmp is the functor ^^^^^ is by typename here.
	qsort(values, count, sizeof(T), cmp);
}

int main( void ) {
	int v[12];
	size_t sz = sizeof(v) / sizeof(int);  
	for (unsigned int i = 0; i < sz; i++) v[i] = rand()%100;
	for (unsigned int i = 0; i < sz; i++ ) {
		std::cout << " " << v[i] ; std::cout << std::endl;
	}
	auto sort_lambda = [&](const void *v1, const void *v2){
		if (*(const T*)v1 < *(const T*)v2) return -1;
		else if (*(const T*)v2 < *(const T*)v1) return 1;
		else return 0;
	}
	my_qsort(v, sz, sort_lambda);
	// the function ^^^^^^^^^^^ is passed as with auto.
	for (unsigned int i = 0; i < sz ; i++) {
		std::cout << " " << v[i] ; std::cout << std::endl;
	}
	return 0;
}
auto it = c.cbegin();

C++ Compiling and Debugging:

Steps of Compiler in C++:

C++ Compiling Command:

GNU debugger, GDB:

Memory Track, valgrind:

C++ References:

Reference type:

void swap(int& a, int& b) { // Swaps two ints by reference.
    int tmp = a;
    a = b;
    b = tmp;
}

References in functions:

const references:

I/O in C++:

<iostream> header in C++:

<fstream> header in C++:


#include <iostream>

#include <fstream>
int main() {
	std::ofstream ofile( "hello.txt" );
	ofile << "Hello, World!" << std::endl; 
	return 0;
}

#include <iostream>

#include <fstream>

#include <string>
int main() {
	std::ifstream ifile( "hello.txt" );
	if (!ifile.is_open()) {
		std::cout << "failed to open hello.txt" << std::endl;
		// indicate that open fails
		return 1;
	}
	std::string word; 
	while (ifile >> word) {
		std::cout << word << std::endl;
		// prints each word in ifile
	}
	return 0;
}

stringstream as buffer:


#include <iostream>

#include <sstream>
int main(){
	std::stringstream ss;  
	ss << "Hello, world!" << std::endl;    // Stores the string in.
	std::cout << ss.str();                 // Return it as a string.
	return 0;
}

Object Oriented Programming from ios:

C++ Standard Template Library:

C++ Namespaces:

using std::cout;
using std::endl;
// More to be added if needed.
	typedef map<int, string> TMap;      // map type
	typedef TMap::iterator TMapItr;     // map iterator type
	// or using:
	using TMap = map<int,string>;       // map type
	using TMapItr = TMap::iterator;     // map iterator type

string in C++:

string s1 = "world";   // intialization directly
string s2("hello");    // intialization directly
string s3(3, 'a');     // intialize as "aaa"
string s4;             // intialize empty string
string s5 = s2;        // deep copy of s2 to s5

| Operator | Usage | |:——–:|——-| | = | assigning literal to string| | >> | put one whitespace-delimited stream input | | << | write the string to output stream | | getline(stream, string) | read to end of line from the stream | | = | deep copying | | + | returning new string being concatenation | | += or s1.append(s2) | appending one string to the end of another | | == != < > <= >=| relational operators, compare by char order |

Templates in C++:

template<typename T>
struct Node {  
   T payload; // 'T' is placeholder for a type Node *next;
   Node *next;
};

template<typename T>
void print_list(Node *head) {
    Node<T> *cur = head;
    while(cur != NULL) {
        cout << cur->payload << " ";
        cur = cur->next;
    }
    cout << endl;
}
template<typename T>
int sum_every_other(const T& ls) {
	int total = 0;  
	// Specifying typename T for the iterator.
	for (typename T::const_iterator it = ls.cbegin();
	    it != ls.cend(); ++it) {
		total += *it;
		if(++it == ls.cend()) { break; }
	}
	return total;
}

array – fixed-length array

vector – dynamically-sized array:

for (vector<string>::iterator it = names.begin();
	 it != names.end(); ++it) {
	cout << *it <<endl;
}

map – associative list, or dictionary:

pair – quick pair for output:

tuple – pair with unlimited amount of elements:

iterator – quickly iterate through the object:

Type ++it –it Get with *it type
iterator forward back .begin() / .end() -
const_iterator forward back .cbegin() / .cend() const
reverse_iterator back forward .rbegin() / .rend() -
const_reverse_iterator back forward .crbegin() / .crend() const

algorithm – algorithms for functions:

Other templates:

Dynamic Memory Allocation in C++:

Dynamically allocating pointers:

int main() {  
	int *iptr = new int;           // allocate a pointer to int.
	*iptr = 10;
	// more code with iptr.
	delete iptr;                   // deallocate the pointer.
}

Dynamically allocating arrays:

int main() {  
	double *d_array = new double[10];          // allocating the array.
	for(int i = 0; i < 10; i++) {
		std::cout << (d_array[i] = i * 2) << " ";
	}
	std::cout << std::endl;
	delete[] d_array;                          // deallocating the array.
	return 0;
}

Exceptions in C++:

Exceptions:

throw std::exception("exception message");
int main() {  
	vector<int> vec = {1, 2, 3};
	try {
		cout << vec.at(3) << endl;  
	} catch(const std::out_of_range &e) {
		cout << "Out of Range: " << endl << e.what() << endl;
	} catch(const std::logic_error &e) {
		cout << "Logic Error: " << endl << e.what() << endl;
	} catch(const std::exception &e) {
		cout << "Exception: " << endl << e.what() << endl;
	} 
	return 0;
}

Customized Exceptions:


#ifndef EXCEPTION_H

#define EXCEPTION_H

#include <stdexcept>

#include <string>
class PlotException : public std::runtime_error {
public:
	PlotException(const std::string &msg) : std::runtime_error(msg) { }
	PlotException(const PlotException &other) : std::runtime_error(other) { }
	~PlotException() { }
};


#endif // EXCEPTION_H

Object Oriented Programming in C++:

Basic class in C++:

class:

void print() const { /* code in between */ }
class Rectangle {
public:
	double area() const {  
		// definition inside class
		return width * height;         // allowed
	}
// code in between
private:
	double width, height;
};

int main() {
	Rectangle r;
	std::cout << r.width << std::endl; // not allowed
	return 0;
}

Style for class:

// Rectangle.h

#ifndef RECTANGLE_H

#define RECTANGLE_H
class Rectangle {
	// code in between
	double get_width() const {
		return width;            // short definition inside class
	}
	double get_area() const;     // long definition has prototype only
};

#endif

// Rectangle.cpp

#include "Rectangle.h"
double Rectangle::area() const { // definition outside class
	return width * height;
}

Constructors:

class Rectangle {
public:
    // default constructor for Rectangle
	Rectangle() { /* definition in between */ }
	// code in between
};

int main() {  
	Rectangle r;  // Rectangle's default constructor is called
	return 0;
}
IntAndString() : i(7), s("hello") { }
string s1("Hello");          // invoces a non-default constructor
string s2 = "Hello";         // invoces a non-default constructor as well
class MyThing {
public:
	MyThing(int init) : init(init) { }
    // initializer list      ^^^^ is fine
    void set_i(int init) { this->init = init;}
    // using this pointer  ^^^^^^ to clarify
private:
	int init;
};
// myThing4.cpp:

#include <iostream>

#include <vector>

class MyThing {
public:
	// no default constructor
	MyThing(int init) : init(init) { }
private:  
	int init;
};

int main() {  
	// use list-initialization to initialize the array  
	MyThing s[10] = {{0},{1},{2},{3},{4},{5},{6},{7},{8},{9}};
	// use empty vector and reserve 10 elements
	std::vector<MyThing> s  
	s.reserve(10);  
	for (int i = 0; i < 10; ++i) {
		// initialization using emplace_back  
		s.emplace_back(i);  
	}
	return 0;
}

Destructors:

// sequence.h:
class Sequence {
public:
	Sequence() : array(NULL), size(0) { }
	// The non-default constructor allocates an array
	Sequence(int sz) : array(new int[sz]), size(sz) { 
		for (int i = 0; i < sz; i++) {
			array[i] = i;
		}
	}
	~Sequence() { delete[] array; } // destructor needed
	// more funtionalities
private:
	int *array;
	int size;
};

Initialization and Assignment:

// Copy constructor
Image(const Image& o) : nrow(o.nrow), ncol(o.ncol) {
	// Do a *deep copy*, similarly to the non-default constructor  
	image = new char[nrow * ncol];
	for(int i = 0; i < nrow * ncol; i++) {
		image[i] = o.image[i];
	}
}

// Assignment operator
Image& operator=(const Image& o) {  
	delete[] image; // deallocate previous image memory
	nrow = o.nrow;  
	ncol = o.ncol;  
	image = new char[nrow * ncol];  
	for(int i = 0; i < nrow * ncol; i++) {
        image[i] = o.image[i]; // having deep copy
    }
    return *this; // for chaining
    }

Templated class

// ll_temp.inc:


#include <iostream>
template<typename T> class Node {  
public:
	Node(T pay, Node<T> *nx) : payload(pay), next(nx) { }
	void print() const {  
		const Node<T> *cur = this;
		while(cur != NULL) {
			std::cout << cur->payload << ' ';
			cur = cur->next;
		}
		std::cout << std::endl;
	}
private:  
	T payload;
	Node<T> *next;
};

Overloading:

Function Overloading:

Operator Overloading:

// insertion_eg2.cpp:


#include <iostream> 
#include <vector>
using std::cout; using std::endl; using std::vector; using std::ostream;

ostream& operator<<(ostream& os, const vector<int>& vec) { 
	for (vector<int>::const_iterator it = vec.cbegin();
	     it != vec.cend(); ++it) {
		os << *it << ' ';
	}
	return os;
}

int main() {  
	const vector<int> vec = {1, 2, 3};  
	cout << vec << endl;    // this prints with overload operator <<.
	return 0;
}
// rational.h
class Rational {
public:
	//...
	Rational operator+(const Rational& right) const;
private:  
	int num; //numerator
	int den; //denominator
};

// rational.cpp
Rational::operator+(const Rational& right) const {
	int sum_num = this->num * right.den + right.num * this->den;
	int sum_den = this->den * right.den;
	Rational result(sum_num, sum_den);
	return result;
}

friend keyword:

// rational.h
class Rational {
public:
	// ...
	friend ostream& operator<<(ostream& os, const Rational& r);
private:
	int num; //numerator
	int den; //denominator
};

// rational.cpp

#include "rational.h"
ostream& operator<<(ostream& os, const Rational& r) {
	os << r.num << "/" << r.den << ' ';
	return os;
}

class Structures:

Inheritance:

// account.h:
class Account {
public:
    Account() : balance(0.0) { }
    Account(double initial) : balance(initial) { }
	void credit(double amt) { balance += amt; }
	void debit(double amt) { balance -= amt; }
	double get_balance() const { return balance; }
	
private:  
	double balance;
};

class SavingsAccount : public Account {
public:
    SavingsAccount(double initial, double rate) :
    Account(initial), annual_rate(rate) { }
    // member function, defined in .cpp file
    double total_after_years(int years) const;
    
private:  
	double annual_rate;
};
class A { ... };
class B { ... };
class C: public A, public B { ... };

Polymorphism:

Account *acc = new SavingsAccount(100.0, 5.00);
void print_account_type(const Account& acct) {
    cout << acct.type() << endl;
}

int main() {
    //...
    SavingAccount saving_acct(100.0, 5.00);
    print_account_type(saving_acct);
    return 0;
}
class Account {
public:
	// ...
	virtual std::string type() const { return "Account"; }
	// ...
};

class SavingsAccount : public Account {
public:
	// ...  
	virtual std::string type() const { return "SavingsAccount"; }
	// ...
};

Dynamic Dispatch:

class Account {
public:
	virtual string type() const { return "Account"; }
};

class SavingAccount : public Account {
public:
	virtual string type() const override { return "SavingAccount"; }
	// use override in derived  ^^^^^^^^ class defensively
};

Abstract Class:

class Shape {
public:
	virtual double size() const = 0;
	// ...
};

UML Diagram:

Iterators for Containers:

// MyNode.h

#ifndef MYNODE_H

#define MYNODE_H

// A single node holding payload data of any type
template <typename T>
class MyNode {
	public:
	T data;          // payload
	MyNode<T> *next; // pointer to following node
	// two-argument constructor
	MyNode<T>(int d, MyNode<T>* n) : data(d), next(n) { }
};  


#endif

// MyList.h

#ifndef MYLIST_H

#define MYLIST_H


#include <iostream>

#include "MyNode.h"

// A linked list template
template<typename T>
class MyList {
	private:
	MyNode<T>* head; // pointer to first node in linked list
	public:
	// nested class for iterator
	class iterator {
		MyNode<T>* ptr;
		public:
		iterator(MyNode<T>* initial) : ptr(initial) { }
		iterator& operator++() {
			ptr = ptr->next;
			return *this;
		}
		bool operator!=(const iterator& o) const {
			return this->ptr != o.ptr;
		}
		T& operator*() { return *ptr; }
		T* operator->() { return ptr; }
	};
	iterator begin() { return iterator(head); }
	iterator end() { return nullptr; }

	class const_iterator {
		const MyNode<T>* ptr;
		public:
		const_iterator(const MyNode<T>* initial) : ptr(initial) { }
		const_iterator& operator++() {
			ptr = ptr->next;
			return *this;
		}
		bool operator!=(const iterator& o) const {
			return this->ptr != o.ptr;
		}
		const T& operator*() { return *ptr; }
		const T* operator->() { return ptr; }
	};
	const_iterator cbegin() const { return const_iterator(head); }
	const_iterator cend() const { return nullptr; }

  // MyList constructor which takes a begin and end iterator.
	template<typename Itr>
	MyList<T>(Itr i_begin, Itr i_end) {
		MyNode<T>* ptr = head;
		while (i_begin != i_end) {
			*ptr = new MyNode<T>(i_begin->data, nullptr);
			ptr = ptr->next;
			++i_begin;
		}
	};

	MyList<T>() : head(nullptr) { } // create empty linked list
    
	~MyList<T>() {                // deallocate all nodes
		while(head != nullptr) {
		    MyNode<T> *next = head->next;
		    delete head;
		    head = next;
		}
	}

	void insertAtHead(const T& d) {  // create new MyNode and add at head
		head = new MyNode<T>(d, head);
	}

	void insertAtTail(const T& d) {  // create new MyNode and add at tail
		if(head == nullptr) {
		    head = new MyNode<T>(d, nullptr);
		} else {
			MyNode<T>* cur = head;
		    while(cur->next != nullptr) {
			    cur = cur->next;
		    }
	    cur->next = new MyNode<T>(d, nullptr);
		}
	}

  // get const pointer to head node
  const MyNode<T>* get_head() const { return head; }

};


#endif



🌞
If you find any questions, please contact me via Contact tab.