C++ is a programming language that is especially well suited for computationally intensive programs and for interfacing with hardware or the operating system. In this chapter, we describe C++ starting with low-level features such as variable types, operators, pointers, arrays, I/O, and control flow, and concluding with object-oriented programming and the standard template library. We consider the latest version of C++ at the time of writing: C++17.
Note: The examples below are abridged; the book contains more details.
// this is a comment.
/* this is another comment
that spans multiple lines. */
int main() {
return 0; // return a value 0 to the operating system
}
#!/bin/bash
cd `dirname "$0"`
# compile and link foo.cpp into an executable file named foo
g++ foo.cpp -o foo
# compile (but do not link) the C++ code in foo.cpp
# into the object file foo.o
g++ -c foo.cpp -o foo.o
# link the object file foo.o and create an executable file foo
g++ foo.o -o foo
# compile multiple C++ files into a single executable, using the C++11 standard,
# optimized compilation, and linking to the standard mathematical library
g++ -o foo -lm -O3 -std=c++0x foo.cpp
# compile and link to create an executable file foo
g++ -o foo foo.cpp
# run the executable file foo (in the current directory)
./foo
# display value returned by the compiled program
echo $?
// Example 1
int age; // age is a variable of type int (integer)
// two double variables
double height;
double weight;
// Example 2
int age = 32; // integer variable holding 32
double height; // unassigned variable
float pi = 3.14; // new float variable
float pi_squared = pi * pi; // new float variable
height = (5 * 30.48) + (10 * 2.54); // assigs a value to height
// Example 3
int a = 2;
const int b = 3; // more readable
int const c = 5; // alternative form
a = 6; // ok
b = 6; // error (b cannot be modified)
// Example 4
double height = 58.0;
double weight = 155.2;
auto bmi = weight / (height * height); // inferred type (double)
// Example 1
{
int a = 2;
a = a + 1; // ok, a is recognized
{
int b = a; // ok, a is still in scope
}
a = b; // error, b is out of scope and is undefined
}
a = a + 1; // error, a is out of scope
// Example 2
int a = 2;
{
int a = 3; // inner a (a=3) masks the outer a (a=2)
int b = a; // b is assigned the value 3
}
// inner a is out of scope and outer a is no longer masked
int c = a; // c is assigned the value of the outer a (a=2)
int d = b; // error: b is no longer in scope
// Example 3
int a = 42; // global variable
int main() {
int a = 13; // local variable
int b = a + 1; // 14
int c = ::a + 1; // 43
return 0;
}
bool result;
result = (3 == 3); // result equals true
result = (3 > 3); // result equals false
int a = 3;
int b;
b = ++a; // b and a both equal 4
result = ((4 > 3) && (4 < 5)); // result equals true
result = !(1 > 2); // result equals true
a = 10 % 3; // a equals 1 (remainder after dividing 10 by 3)
b = (a = 5); // assign 5 to a, and then assign that value to b
// Example 1
int i;
double d = 58.3;
i = (int) d; // converts 58.3 to int
// Example 2
int a = 3.2; // 3.2 is converted to the integer 3
int b;
b = 3.2; // same casting as above
b = 3.0 / 2.0; // 1.5 is converted to the integer 1
// Example 3
int a = 1;
int b = 2;
float f = 2.0f; // without the suffix f, 2.0 is a double
// Below, in the division a/f, the integer a is converted
// to a float resulting in a division of two floats:
// 1.0f/2.0f (which equals 0.5)
float g = a / f; // g equals 0.5
// Below, there is no type conversion for the division a/b.
// The division of an integer 1 by another integer 2 gives
// the integer 0, which is then converted to a float 0.0
// that is assigned to h
float h = a / b; // h equals 0.0
int a = 2;
int c = 3;
int &refA = a; // refA is a reference to the variable a
int b = refA; // has same effect as b = a
refA = 5; // has same effect as a = 5
int &refC1 = c;
int &refC2 = c; // both refC1 and refC2 refer to c
// Example 1
int *pa;
int *pb; // pa and pb are pointers to int variables
float *fx;
float *fy; // fx and fy are pointers to float variables
// Example 2
int a = 2;
int *b; // uninitialized pointer - may contain unexpected address
int *c = &a; // address of variable a is assigned to pointer c
int d = *c; // value at address c is assigned to d (d = 2)
// define a new pointer e that points to the same memory as c
int *e = c;
float f = 3.0f;
float *fp = &f; // ok
int *a = &f; // problem: a is of type int* but points to float
// Example 3
int a = 2;
int *b = &a; // pointer b points to a
int **c = &b; // double pointer c points to b
// c now holds the address of b, which holds the address of a
int *d = *c; // contents of b (address of a) is assigned to d
int e = *(*c); // contents of a (2) is assigned to e
// Example 1
int a[10]; // define an array of 10 integers
a[0] = 1; // assign 1 to the first element
a[3] = 2; // assign 2 to the fourth element
int b = a[3]; // assign to b the contents of the fourth element
// Example 2
// using an array as a pointer
int a[10];
*a = 3; // assign a value of 3 to the first element
*(a + 2) = 4; // assign a value of 4 to the third element
// using a pointer as an array
int *pA = a + 1; // pA points to the second element of a
pA[1] = 5; // assign a value of 5 to the third element of a
// Example 3
// define an array of size 10 containing the integers 0, 1,..., 9
int a[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
// array size may be omitted in this case
int a[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
// define an array of size 10 initialized to default
// values (0 for int)
int a[10] = {};
// define an array of size 10 initialized to 1, 0,..., 0
int a[10] = {1};
// Example 4
const int N = 3;
double a[N]; // ok
int m = 3;
double b[m]; // error
// Example 5
int a[10] = {};
a[13] = 3; // dangerous bug - possible erratic behavior
// Example 6
// a is 3 by 4 table of integers initialized to default values
// (0 in the case of int variables)
int a[3][4] = {};
a[0][0] = 2; // assign 2 to first row, first column element
a[0][1] = 3; // assign 3 to first row, second column element
a[1][2] = 4; // assign 4 to second row, third column element
// b is 3 by 4 by 5
int b[3][4][5] = {};
b[0][0][0] = 2; // first row, first column, first layer element
b[0][1][2] = 2; // first row, second column, third layer element
// include the C++ input and output header file
#include <iostream>
// the statement below prints 3 (cout is an output stream defined
// in the header file iostream)
int main() {
std::cout << 3;
return 0;
}
// Example 1
// include a header file written by the programmer
#include "my_header_file.h"
// call my_function, which is a function defined in
// the header file my_header_file.h
int main() {
my_function();
return 0;
}
// Example 2
#define WIDTH 80
int page_width = WIDTH;
int two_page_width = 2 * WIDTH;
// This code below is similar but harder to comprehend
// and maintain
int three_page_width = 3 * 80;
int four_page_width = 4 * 80;
// Example 3
#include <iostream>
#define arraysize(array) (sizeof(array) / sizeof(*array))
int main() {
int a[10];
std::cout << arraysize(a); // prints the size of the array (10)
return 0;
}
// Example 4
#include "my_header_file1.h"
#include "my_header_file2.h"
// constants or functions in my_header_file3 are defined twice
// Example 5
#ifndef _MY_HEADER_3_GUARD
#define _MY_HEADER_3_GUARD
// copy original contents of my_header_file3.h here
#endif
// Example 6
// option 1: Prefix cout by the namespace name and ::
std::cout << 3; // print 3 (cout is defined std namespace)
// option 2: Using namespace std allows dropping the std:: prefix
using namespace std;
cout << 3;
#include <string>
using namespace std;
int main() {
string s1; // define an empty string
string s2 = "hello world"; // define a string with content
int sz = s2.size(); // assign size of string s2 to variable
char a = s2[1]; // access second character of s2 ('e')
string s3 = s2 + s2; // concatenate s2 with itself
bool b = s2.empty(); // true if s2 is an empty string
return 0;
}
#include <string>
using namespace std;
int main() {
int a = 123;
string s = to_string(a); // assign "123" to s
int i = stoi(s); // assign integer 123 to i
double d = stod(s); // assign floating point 123.0 to d
return 0;
}
#include <iostream>
#include <string>
using namespace std;
int main() {
string s1, s2;
// read a string delimited by white space from standard
// input into s1
cin >> s1;
// read two strings separated by white spaces (first into s1
// and then into s2)
cin >> s1 >> s2;
return 0;
}
#include <iostream>
#include <string>
using namespace std;
int main() {
int c, d;
// read buffered data from the standard input stream,
// convert the first two inputs into integers, and
// store them in c and d
cin >> c >> d;
return 0;
}
#include <iostream>
#include <string>
using namespace std;
int main() {
string s;
// read a line (possibly containing white spaces)
// from standard input and assign it to s
getline(cin, s);
return 0;
}
#include <iostream>
#include <string>
using namespace std;
int main() {
string s = "hello world";
// display hello world followed by an end of line
cout << s << endl;
// display hello world followed by ! and end of line
cout << s << "!" << endl;
return 0;
}
// Example 1
int a;
int abs_a;
cin >> a; // read a from terminal
// replace a by its absolute value and store it in abs_a
if (a < 0) {
abs_a = -a; // if a is negative, use -a
} else {
abs_a = a; // if a is non-negative, use a
}
// Example 2
int a;
int abs_a;
cin >> a;
abs_a = a;
// negate abs_a if it is negative
if (abs_a < 0) {
abs_a = -abs_a;
}
// Example 3
int a;
cin >> a;
int abs_a = a < 0 ? -a : a;
// Example 1
// Assigns 4! = 4 * 3 * 2 = 24 to the variable fac_val
// 3 loop iterations will be executed (on fourth iteration the
// condition 1 > 1 fails).
int val = 4;
int fac_val = 1;
while (val > 1) {
fac_val = fac_val * val;
val = val - 1;
}
// Example 2
// similar to previous example with break statement
int val = 4;
int fac_val = 1;
while (1) {
if (val <= 1) {
break;
}
fac_val = fac_val * val;
val = val - 1;
}
// Example 3
// computes = 4 * 2 (iteration that multiplies by 3 is skipped)
int val = 4;
int fac_val_mod = 1;
while (1) {
if (val == 3) {
val = val - 1;
continue;
}
if (val <= 1) {
break;
}
fac_val_mod = fac_val_mod * val;
val = val - 1;
}
#include <iostream>
using namespace std;
int main() {
int an_array[10];
int i;
// initialize an_array to hold 0, 1, ..., 9
// 10 iterations are executed, corresponding to
// i = 0, 1, ..., 9
for (i = 0; i < 10; ++i) {
an_array[i] = i;
}
// print the values of the array on a single line
for (i = 0; i < 10; ++i) {
cout << an_array[i] << ' ';
}
cout << endl;
return 0;
}
#include <iostream>
using namespace std;
int main() {
int an_array[10];
int i = 0;
for (auto &element : an_array) {
element = i;
++i;
}
for (auto &element : an_array) {
cout << element << ' ';
}
cout << endl;
return 0;
}
#include <iostream>
using namespace std;
int main() {
int i;
int j;
const int N = 10;
int a_table[N][N]; // NxN 2D array
// initialize table to hold the values 0, 1, ..., 99
for (i = 0; i < N; ++i) {
for (j = 0; j < N; ++j) {
a_table[i][j] = i * N + j;
}
}
// print the table
for (i = 0; i < N; ++i) {
for (j = 0; j < N; ++j) {
cout << a_table[i][j] << ' ';
}
cout << endl;
}
return 0;
}
# include <iostream>
using namespace std;
// function print_two() prints 2 to standard output
void print_two() {
cout << 2 << endl;
}
int main() {
cout << 1 << endl;
print_two(); // execute the function print_two
cout << 3 << endl;
return 0;
}
# include <iostream>
using namespace std;
// function return_two returns an int variable that equals 2
int return_two() {
return 2;
}
int main() {
cout << 1 << endl;
cout << return_two() << endl; // print returned value
cout << 3 << endl;
return 0;
}
#include <iostream>
using namespace std;
int add_two(int a, int b) {
return a + b;
}
int main() {
// print the value 3 returned by add_two(1, 2)
cout << add_two(1, 2) << endl;
return 0;
}
// Example 1
int add_two(int x, int y) { // function definition
return x + y;
}
int add_two(int x, int y); // function declaration
// Example 2
#include "factorial.h"
int main() {
cout << my_factorial(3) << endl;
return 0;
}
#include <iostream>
#include <string>
using namespace std;
// return a * b
int multiply_two(int a, int b) {
int c = a * b;
return c;
}
int main() {
cout << multiply_two(2, 3) << endl; // prints 6
int b = 4;
int c = 5;
cout << multiply_two(b, c) << endl; // prints 20
cout << c << endl; // print value of local c (5)
return 0;
}
#include <iostream>
using namespace std;
// The function below accepts an address and
// an integer n and communicates back by writing
// the first n non-negative even integers in
// the specified address
void write_seq(int *a, int n) {
for (int i = 0; i < n; ++i) {
a[i] = i * 2;
}
}
// The function below accepts an address and
// an integer n and negates the n integers
// that are stored in the specified address
void negate_seq(int *a, int n) {
for (int i = 0; i < n; ++i) {
a[i] = -a[i];
}
}
int main() {
int a[10] = {};
write_seq(a, 10); // assign even numbers to the array
negate_seq(a, 10); // negate values of a
for (const auto &element : a) {
cout << element << " ";
}
cout << endl;
return 0;
}
#include <iostream>
using namespace std;
// The function modifies variables in the calling environment by
// receiving parameters of type reference, and then modifying
// the variables that are referred to.
void set(int &a, int &b, int &c) {
a = 1;
b = 2;
c = 3;
}
int main() {
int a = 0;
int b = 0;
int c = 0;
// print initial values
cout << a << ' ' << b << ' ' << c << endl;
// modify the local a, b, c by passing references to them.
set(a, b, c);
// print values of a, b, c
cout << a << ' ' << b << ' ' << c << endl;
return 0;
}
So far, we have seen examples of main
calling other functions.
It’s possible for any function to call another; for example:
#include<iostream>
using namespace std;
void bar() {
cout << "bar" << endl;
}
void foo() {
cout << "foo" << ' ';
bar();
}
int main() {
// enter foo and print "foo", then enter bar and print "bar"
foo();
return 0;
}
In fact, it’s possible for a function to call itself:
// recurse() will keep calling itself, going into deeper
// and deeper recursive calls
// (until the program crashes due to call stack overflow)
void recurse() {
recurse();
}
int main() {
recurse();
return 0; // this statement will never be reached
}
In the example below, the recursive function contains a stopping condition
(n == 1
), which stops the recursion when met:
#include <iostream>
using namespace std;
int factorial(int n) {
if (n == 1) {
return 1;
}
return n * factorial(n - 1);
}
int main() {
cout << factorial(3) << endl; // prints 6
return 0;
}
#include <iostream>
using namespace std;
int factorial(int n) {
cout << "entering factorial(" << n << ')' << endl;
if (n == 1) {
cout << "leaving factorial(1) with return value 1" << endl;
return 1;
}
int result = n * factorial(n - 1);
cout << "leaving factorial(" << n <<
") with return value " << result << endl;
return result;
}
int main() {
cout << factorial(3) << endl;
return 0;
}
// running the program ./my_prog from the Linux terminal
// calls the appropriate main function with parameters a, 1, b, 2
// ./my_prog a 1 b 2
#include <iostream>
using namespace std;
int main(int argc, char **argv) {
cout << "argc is: " << argc << endl;
for (int i = 0; i < argc; ++i) {
cout << "argv[" << i << "] is: " << argv[i] << endl;
}
return 0;
}
#include <iostream>
using namespace std;
void print_argument(int a) {
cout << "One int argument passed: " << a << endl;
}
void print_argument(double a) {
cout << "One double argument passed: " << a << endl;
}
void print_argument() {
cout << "No argument passed" << endl;
}
int main() {
print_argument(); // matches print_argument()
print_argument(1); // matches print_argument(int)
print_argument(1.2); // matches print_argument(double)
return 0;
}
struct Point {
double x;
double y;
};
int main() {
Point p1; // instantiation of object p1
Point p2; // instantiation of object p2
p1.x = 3;
p1.y = 0;
}
#include <iostream>
#include <string>
using namespace std;
struct Person {
string name;
double age;
};
void by_address_of_const(const Person *p) {
Person x;
p = &x;
cout << "modified copy inside function: " << p << endl;
}
int main() {
Person person;
Person *pointer = &person;
cout << "before function call: " << pointer << endl;
by_address_of_const(pointer);
cout << "after function call: " << pointer << endl;
return 0;
}
#include <iostream>
using namespace std;
struct Point {
double x;
double y;
};
// pass by reference - the function is modifying p
void scale_point(Point &p, double scaling_factor) {
p.x = p.x * scaling_factor;
p.y = p.y * scaling_factor;
}
// pass by const reference - the function is not modifying p
void print_point(const string &prefix, const Point &p) {
cout << prefix << '(' << p.x << ',' << p.y << ')' << endl;
}
// pass by const reference - the function is not modifying p1, p2
Point subtract_points(const Point &p1, const Point &p2) {
Point delta;
delta.x = p1.x - p2.x;
delta.y = p1.y - p2.y;
return delta;
}
int main() {
Point p1;
Point p2;
p1.x = 1;
p1.y = 2;
p2.x = 3;
p2.y = 3;
print_point("first point: ", p1);
print_point("second point: ", p2);
print_point("delta: ", subtract_points(p1, p2));
// scale second point by a factor of 2
cout << endl << "scaling the 2nd point to 2x" << endl;
scale_point(p2, 2);
print_point("first point: ", p1);
print_point("second point: ", p2);
print_point("delta:", subtract_points(p1, p2));
return 0;
}
#include <iostream>
#include <cmath>
using namespace std;
struct Point {
double x;
double y;
};
struct Vector {
Point start;
Point end;
};
// pass by const reference; the function doesn't modify p1 or p2
Point subtract_points(const Point &p1, const Point &p2) {
Point delta;
delta.x = p1.x - p2.x;
delta.y = p1.y - p2.y;
return delta;
}
double length(const Vector &v) {
Point diff = subtract_points(v.start, v.end);
return sqrt(diff.x * diff.x + diff.y * diff.y);
}
int main() {
Vector v;
v.start.x = 1;
v.start.y = 0;
v.end.x = 2;
v.end.y = 1;
cout << "length of the vector is: " << length(v) << endl;
}
#include <iostream>
using namespace std;
struct Point {
double x;
double y;
};
int main() {
// create an array of two points
Point points[2];
// initialize the array to (0,1) and (2,3)
points[0].x = 0;
points[0].y = 1;
points[1].x = 2;
points[1].y = 3;
// points is a pointer that refers to the start of the array
// print points[0] using -> syntax
cout << points->x << ' ' << points->y << endl;
// print points[1] using . syntax
cout << points[1].x << ' ' << points[1].y << endl;
}
#include <iostream>
using namespace std;
class Point {
private:
// fields are accessible only to methods belonging to point
double x;
double y;
public:
void set_x(double a_x) {
this->x = a_x; // set the member x to the value a_x
}
void set_y(double a_y) {
this->y = a_y;
}
// get value of x, const implies that the method does not
// modify the object
double get_x() const {
return x;
}
// get value of y, const implies that the method does not
// modify the object
double get_y() const {
return y;
}
// negate x and y (method implemented outside class body)
void reflect();
};
void Point::reflect() {
x = -x; // alternatively, this->x = - this->x
y = -y; // alternatively, this->y = - this->y
}
int main() {
Point p;
p.set_x(1);
p.set_y(2);
cout << '(' << p.get_x() << ',' << p.get_y() << ')' << endl;
p.reflect();
cout << '(' << p.get_x() << ',' << p.get_y() << ')' << endl;
return 0;
}
#include <iostream>
using namespace std;
class Point {
private:
// fields are accessible only to methods belonging to point
double x;
double y;
public:
// empty constructor, called by the statement: Point p;
Point() {}
// constructor accepting two arguments, called by a
// statement such as: Point p(1, 2);
Point (double a_x, double a_y) {
this->x = a_x;
this->y = a_y;
}
// get value of x, const implies that the method does not
// modify the object
double get_x() const {
return x;
}
// get value of y, const implies that the method does not
// modify the object
double get_y() const {
return y;
}
};
int main() {
Point p(2,-2); // constructor with two argument is called
cout << '(' << p.get_x() << ',' << p.get_y() << ')' << endl;
return 0;
}
#include <iostream>
using namespace std;
class Point {
private:
// fields are accessible only to methods belonging to point
double x;
double y;
public:
// empty constructor, called by the statement: Point p;
Point() {}
// constructor accepting two arguments, called by a
// statement such as: Point p(1, 2);
Point(double a_x, double a_y) : x(a_x), y(a_y) {}
// get value of x, const implies that the method does not
// modify the object
double get_x() const {
return x;
}
// get value of y, const implies that the method does not
// modify the object
double get_y() const {
return y;
}
};
int main() {
Point p(2,-2); // constructor with two argument is called
cout << '(' << p.get_x() << ',' << p.get_y() << ')' << endl;
return 0;
}
#include <iostream>
using namespace std;
class Point {
private:
// fields are accessible only to methods belonging to point
double x;
double y;
public:
// empty constructor, called by the statement: Point p;
Point() {}
// constructor accepting two arguments, called by a
// statement such as: Point p(1, 2);
Point(double a_x, double a_y) : x(a_x), y(a_y) {}
~Point() {} // empty destructor
// get value of x, const implies that the method does not
// modify the object
double get_x() const {
return x;
}
// get value of y, const implies that the method does not
// modify the object
double get_y() const {
return y;
}
};
int main() {
Point p(2,-2); // constructor with two argument is called
cout << '(' << p.get_x() << ',' << p.get_y() << ')' << endl;
return 0;
}
#include <iostream>
using namespace std;
class Point {
private:
// fields are accessible only to methods belonging to point
double x;
double y;
public:
// constructor accepting two arguments, called by a
// statement such as: Point p(1, 2);
Point(double a_x, double a_y) : x(a_x), y(a_y) {}
// copy constructor
Point(const Point& p) {
x = p.x;
y = p.y;
}
};
int main() {
Point p1(1, 2); // new object using a constructor
Point p2(p1); // new object using the copy constructor
return 0;
}
#include <iostream>
using namespace std;
class Element {
private:
int atomic_number;
public:
Element(int an_atomic_number) :
atomic_number(an_atomic_number) {}
int get_atomic_number() const {
return atomic_number;
}
};
int main() {
Element na(11);
Element mg = 12; // alternative form
cout << mg.get_atomic_number() << endl; // prints 12
return 0;
}
#include <iostream>
using namespace std;
class Element {
private:
int atomic_number;
public:
Element(int an_atomic_number) :
atomic_number(an_atomic_number) {}
int get_atomic_number() const {
return atomic_number;
}
};
// calling this function with an int parameter causes
// the converting constructor to be called
void print_element(Element x) {
cout << x.get_atomic_number() << endl;
}
int main() {
print_element(12); // prints 12
return 0;
}
#include <iostream>
using namespace std;
class Element {
private:
int atomic_number;
public:
// note the use of the explicit keyword below
explicit Element(int an_atomic_number) :
atomic_number(an_atomic_number) {}
int get_atomic_number() const {
return atomic_number;
}
};
int main() {
Element na(11);
Element mg = 12; // error
cout << na.get_atomic_number() << endl; // prints 11
return 0;
}
#include <iostream>
using namespace std;
class Point {
private:
// fields are accessible only to methods belonging to point
double x;
double y;
public:
Point() {}
// constructor accepting two arguments, called by a
// statement such as: Point p(1, 2);
Point(double a_x, double a_y) : x(a_x), y(a_y) {}
// get value of x, const implies that the method does not
// modify the object
double get_x() const {
return x;
}
// get value of y, const implies that the method does not
// modify the object
double get_y() const {
return y;
}
// overload addition operator (+)
Point operator+(const Point &p) const {
Point result;
result.x = this->x + p.x;
result.y = this->y + p.y;
return result;
}
};
ostream& operator<<(ostream& os, const Point &p) {
os << '(' << p.get_x() << ',' << p.get_y() << ')';
return os; // to support operator chaining
}
int main() {
Point p1(1,2);
Point p2(2,3);
Point p3 = p1 + p2; // calls the overloaded + operator
// calls the overloaded << operator thrice for points
// and thrice for spaces and end-of-line delimiters
cout << p1 << ' ' << p2 << ' ' << p3 << endl;
return 0;
}
#include <iostream>
using namespace std;
class Point {
private:
// fields are accessible only to methods belonging to point
double x;
double y;
public:
// constructor accepting two arguments, called by a
// statement such as: Point p(1, 2);
Point(double a_x, double a_y) : x(a_x), y(a_y) {}
// mark the non-member function overloading << as a friend
friend ostream& operator<<(ostream &os, const Point &p);
};
ostream& operator<<(ostream &os, const Point &p) {
// access private fields since << is a friend of Point
os << '(' << p.x << ',' << p.y << ')';
return os;
}
int main() {
Point p(1,2);
cout << p << endl;
return 0;
}
#include <iostream>
using namespace std;
class Point {
private:
// fields are accessible only to methods belonging to point
double x;
double y;
public:
// empty constructor, called by the statement: Point p;
Point() {}
// constructor accepting two arguments, called by a
// statement such as: Point p(1, 2);
Point(double a_x, double a_y) : x(a_x), y(a_y) {}
// get value of x, const implies that the method does not
// modify the object
double get_x() const {
return x;
}
// get value of y, const implies that the method does not
// modify the object
double get_y() const {
return y;
}
void set_x(double a_x) {
this->x = a_x; // set the member x to the value a_x
}
void set_y(double a_y) {
this->y = a_y;
}
};
class NamedPoint : public Point {
private:
string name;
public:
// empty constructor calls point constructor
NamedPoint() : Point() {}
// constructor calls point constructor then initializes name
NamedPoint(double x, double y, string name) :
Point(x, y), name(name) {}
string get_name() {
return name;
}
void set_name(string a_name) {
this->name = a_name;
}
};
int main() {
NamedPoint p(0, 0, "origin");
p.set_name("FIRST POINT");
p.set_x(2); // calls a base class method
cout << p.get_name() << ": " << '(' << p.get_x() << ',' <<
p.get_y() << ')' << endl;
return 0;
}
#include <iostream>
using namespace std;
class Point {
private:
// fields are accessible only to methods belonging to point
double x;
double y;
public:
// constructor accepting two arguments, called by a
// statement such as: Point p(1, 2);
Point(double a_x, double a_y) : x(a_x), y(a_y) {}
void print() { // Point::print method defined in base class
cout << '(' << x << ',' << y << ')' << endl;
}
};
class NamedPoint : public Point {
private:
string name;
public:
// constructor calls point constructor then initializes name
NamedPoint(double x, double y, string name) :
Point(x, y), name(name) {}
// NamedPoint::print method defined in derived class
void print() {
cout << name << ' ';
Point::print();
}
};
int main() {
Point p(2,3);
NamedPoint np(1, 2, "first point");
p.print(); // Point::print is called
np.print(); // NamedPoint::print is called
return 0;
}
The following code demonstrates static binding, which is the default in C++:
#include <iostream>
using namespace std;
class Point {
private:
// fields are accessible only to methods belonging to point
double x;
double y;
public:
// constructor accepting two arguments, called by a
// statement such as: Point p(1, 2);
Point(double a_x, double a_y) : x(a_x), y(a_y) {}
void print() { // Point::print method defined in base class
cout << '(' << x << ',' << y << ')' << endl;
}
};
class NamedPoint : public Point {
private:
string name;
public:
// constructor calls point constructor then initializes name
NamedPoint(double x, double y, string name) :
Point(x, y), name(name) {}
// NamedPoint::print method defined in derived class
void print() {
cout << name << ' ';
Point::print();
}
};
int main() {
NamedPoint p(0, 0, "origin");
Point &refP = p;
Point *pp = &p;
refP.print(); // static binding calls Point::print()
pp->print(); // ditto
return 0;
}
#include <iostream>
using namespace std;
class Point {
private:
// fields are accessible only to methods belonging to point
double x;
double y;
public:
// constructor accepting two arguments, called by a
// statement such as: Point p(1, 2);
Point(double a_x, double a_y) : x(a_x), y(a_y) {}
// Point::print method defined in base class
// note the use of the virtual keyword below
virtual void print() {
cout << '(' << x << ',' << y << ')' << endl;
}
};
class NamedPoint : public Point {
private:
string name;
public:
// constructor calls point constructor then initializes name
NamedPoint(double x, double y, string name) :
Point(x, y), name(name) {}
// NamedPoint::print method defined in derived class
// note the use of the virtual keyword below
virtual void print() {
cout << name << ' ';
Point::print();
}
};
int main() {
NamedPoint p(0, 0, "origin");
Point &refP = p;
Point *pp = &p;
refP.print(); // dynamic binding calls NamedPoint::print()
pp->print(); // ditto
return 0;
}
#include <iostream>
using namespace std;
class Point {
private:
double x;
double y;
static int num_objects;
public:
Point() {
// increments counter when a new object is created
++num_objects;
}
// even though this method does not modify any members,
// static member functions cannot be qualified as const
static int get_num_points() {
return num_objects;
}
};
// defines the static field num_objects and initializes it to 0
int Point::num_objects = 0;
int main() {
Point p1;
Point p2;
Point p3;
cout << "number of point objects: "
<< Point::get_num_points() << endl;
return 0;
}
#include<iostream>
using namespace std;
int count_calls() {
// initialization occurs only once when program is loaded
static int counter = 0;
return ++counter; // pre-increments then returns
}
int main() {
count_calls();
count_calls();
cout << "number of calls: "<< count_calls() << endl;
return 0;
}
int main() {
// pd points to a dynamically allocated double variable
double *pd = new double;
// free the allocated memory
delete pd;
return 0;
}
int main() {
Point *pp1 = new Point; // the default constructor
Point *pp2 = new Point(1, 2); // an overloaded constructor
delete pp1;
delete pp2;
return 0;
}
int main() {
int n = 2;
// allocates memory for an array of n objects of type point
Point *pp = new Point[n];
delete[] pp; // frees up a dynamically-allocated array
return 0;
}
#include<memory>
using namespace std;
int main() {
// creates smart pointers to double variables,
// each holds a value of 4.2
shared_ptr<double> pd1 = make_shared<double>(4.2);
shared_ptr<double> pd2(new double(4.2)); // alternatively
// pd2 is reassigned to a new memory location,
// older memory content is no longer pointed to
// and is therefore freed up automatically
pd2 = make_shared<double>(8.4);
// several shared_ptr objects may point to the same memory
shared_ptr<double> pd3 = pd2;
return 0;
}
#include <memory>
using namespace std;
unique_ptr<int> create_unique_pointer() {
return unique_ptr<int>(new int(4));
}
int main() {
unique_ptr<int> pi1(new int(3));
// error: two unique_ptr pointers pointing to the same memory
unique_ptr<int> pi2 = pi1;
// ok: new unique_ptr takes over as old unique_ptr is destroyed
unique_ptr<int> pi3 = create_unique_pointer();
return 0;
}
#include <iostream>
#include <memory>
using namespace std;
int main() {
int n = 10;
// smart pointer to an array of int variables
unique_ptr<int[]> array(new int[n]);
for (int i=0; i<n; ++i) {
array[i] = i;
}
for (int i=0; i<n; ++i) {
cout << array[i] << ' ';
}
cout << endl;
return 0;
}
#include <iostream>
using namespace std;
class Element {
private:
int atomic_number;
public:
Element(int atomic_number) :
atomic_number(atomic_number) {}
int get_atomic_number() const {
return atomic_number;
}
bool operator<(const Element &x) const {
return this->atomic_number < x.atomic_number;
}
};
// note the use of the template keyword below:
template <class T>
// note the use of const T& to avoid copying the return value
const T& get_min(const T &a, const T &b) {
return a < b ? a : b;
}
int main() {
// calls the template function, replacing T with int
cout << get_min<int>(1, 2) << endl;
// calls the template function, replacing T with double
cout << get_min<double>(9.1, 2.5) << endl;
// calls the template function with an inferred type (int)
cout << get_min(13, 42) << endl;
Element na = 11;
Element mg = 12;
// calls the template function, replacing T with Element
// note that the replacement type, Element, is inferred
cout << get_min(na, mg).get_atomic_number() << endl;
return 0;
}
#include <iostream>
using namespace std;
class Element {
private:
int atomic_number;
public:
Element(int atomic_number) :
atomic_number(atomic_number) {}
int get_atomic_number() const {
return atomic_number;
}
bool operator<(const Element &x) const {
return this->atomic_number < x.atomic_number;
}
};
template <class T, class S>
bool precedes(const T &a, const S &b) {
return a < b;
}
int main() {
// instructs cout to print true and false instead of 1 and 0
cout.setf(ios::boolalpha);
cout << precedes<int, double>(1, 42) << endl;
cout << precedes(9.1, 3) << endl;
cout << precedes(1.5f, 1.3) << endl;
Element na = 11;
Element mg = 12;
cout << precedes(na, mg) << endl;
return 0;
}
#include <iostream>
using namespace std;
template<class T>
class Point {
private:
T x;
T y;
public:
void set_x(const T &x) {
this->x = x;
}
void set_y(const T &y) {
this->y = y;
}
T get_x() const {
return x;
}
T get_y() const {
return y;
}
void reflect() {
x = -x;
y = -y;
}
};
int main() {
Point<int> p;
p.set_x(1);
p.set_y(2);
cout << '(' << p.get_x() << ',' << p.get_y() << ')' << endl;
p.reflect();
cout << '(' << p.get_x() << ',' << p.get_y() << ')' << endl;
return 0;
}
#include <vector>
#include <iostream>
using namespace std;
int main() {
vector<int> v;
for (int i = 0; i < 10; ++i) { // store 1..10
v.push_back(i);
}
for (const auto &x : v) { // print all elements
cout << x << ' ';
}
cout << endl;
return 0;
}
array<int, 10> array; // defines an array of 10 integers
// initializes values of all array elements
for (int i; i < array.size(); ++i) {
array[i] = i;
}
#include <set>
#include <string>
#include <iostream>
using namespace std;
int main() {
set<string> s;
s.insert({"one"});
s.insert({"two"});
s.insert({"three"});
s.insert({"one"});
for (const auto &x : s) {
cout << x << ' ';
}
cout << endl;
return 0;
}
#include <map>
#include <string>
#include <iostream>
using namespace std;
int main() {
multimap<string,int> names;
// note the use of curly braces to create a pair
names.insert({"John", 3});
names.insert({"Peter", 2});
names.insert({"Jane", 6});
names.insert({"Jane", 2});
for (const auto &x : names) {
cout << x.first << ": " << x.second << endl;
}
return 0;
}
#include <map>
#include <string>
#include <iostream>
using namespace std;
int main() {
map<string,int> names;
names["John"] = 3;
names["Jane"] = 6;
cout << "names[\"John\"]: " << names["John"] << endl;
cout << "names[\"Jane\"]: " << names["Jane"] << endl;
return 0;
}
#include <unordered_map>
#include <string>
#include <iostream>
using namespace std;
int main() {
unordered_multimap<string,int> names;
names.insert({"John", 3});
names.insert({"Peter", 2});
names.insert({"Jane", 6});
names.insert({"Jane", 2});
for (const auto &x : names) {
cout << x.first << ": " << x.second << endl;
}
return 0;
}