CMS
Introduction to Basic C++ for Programmers — Part 2
*.h
, *.hpp
)
#include
d by all files using the corresponding .cpp
fileby_value.cpp
/** * Demo for pass by value. * Copyright 2015 Gerald Senarclens de Grancy <oss@senarclens.eu> */ #include <iostream> void pass_by_value(int i) { i = 5; std::cout << "i: " << i << " (at end of called function)" << std::endl; } int main() { int i = 3; std::cout << "i: " << i << std::endl; pass_by_value(i); std::cout << "i: " << i << " (after returning from function)" << std::endl; return 0; }
i: 3 i: 5 (at end of called function) i: 3 (after returning from function)
by_reference.cpp
/** * Demo for pass by reference. * Copyright 2015 Gerald Senarclens de Grancy <oss@senarclens.eu> */ #include <iostream> void pass_by_reference(int& i) { i = 5; std::cout << "i: " << i << " (at end of called function)" << std::endl; } int main() { int i = 3; std::cout << "i: " << i << std::endl; pass_by_reference(i); std::cout << "i: " << i << " (after returning from function)" << std::endl; return 0; }
i: 3 i: 5 (at end of called function) i: 5 (after returning from function)
copy_assignment.cpp
#include <iostream> #include <vector> template <class Type> void print_vector(std::vector<Type>& v) { for (Type& elem : v) { std::cout << elem << " "; } std::cout << std::endl; } int main() { std::vector<int> v1(5); std::vector<int> v2 = v1; // this is copy assignment, not a reference std::vector<int>& v3 = v1; // this is a reference v1[1] = 7; v2[3] = 2; v3[2] = 4; print_vector(v1); print_vector(v2); print_vector(v3); }
0 7 4 0 0 0 0 0 2 0 0 7 4 0 0
main.cpp
#include <iostream> #include "circle.hpp" int main () { try { Circle c1(3, 5, 2); Circle c2(6, 5, 1); std::cout << c1 << std::endl; std::cout << "circumference: " << c1.circumference() << std::endl; std::cout << c2 << std::endl; std::cout << "area: " << c2.area() << std::endl; return 0; } catch (...) { std::cerr << "Oops: unknown exception!\n"; return 2; } }
circle.hpp
#ifndef CIRCLE_H // header guard prevents multiple inclusion #define CIRCLE_H #include <cmath> class Circle { public: Circle(double x, double y, double radius); double x() const {return m_x;} // automatically inlined getter function double y() const {return m_y;} // getters are const => object is not changed double radius() const {return m_radius;} double area() const {return m_radius * m_radius * M_PI;} double circumference() const {return 2 * m_radius * M_PI;} private: // private members cannot be accessed w/out accessor functions double m_x; // either prepend `m_` or append `_` to members double m_y; double m_radius; }; std::ostream& operator<<(std::ostream& os, const Circle& c); #endif // CIRCLE_H
circle.cpp
#include <iostream> #include "circle.hpp" Circle::Circle(double x, double y, double radius) : m_x(x), m_y(y) { if (radius < 0) { throw "Circle cannot have radius < 0."; // bad style... } m_radius = radius; } std::ostream& operator<<(std::ostream& os, const Circle& c) { os << "Circle(" << c.x() << ", " << c.y() << ", " << c.radius() << ")"; return os; }
# *.hpp files don't need to be compiled separately as they are included g++ main.cpp circle.cpp -o circle # vs g++ -c main.cpp g++ -c circle.cpp g++ main.o circle.o -o circle
Makefile
s quickly get hard to writeMakefile
CFLAGS := -g -std=c++11 -Wall -Wextra -Wconversion -O2 LINK_FLAGS := CC := g++ OUTFILE := circle .PHONY: all clean # .PHONY avoids problems with targets that aren't files all: $(OUTFILE) $(OUTFILE): main.o circle.o $(CC) $(CFLAGS) -o $(OUTFILE) main.o circle.o $(LINK_FLAGS) main.o: main.cpp circle.cpp circle.hpp $(CC) $(CFLAGS) -c main.cpp $(LINK_FLAGS) circle.o: circle.cpp circle.hpp $(CC) $(CFLAGS) -c circle.cpp $(LINK_FLAGS) clean: rm main.o circle.o $(OUTFILE)
make # ... make clean
CMakeLists.txt
# CMakeLists to build simple circle application set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -std=c++11 -Wall -Wextra -Wconversion -O2") set(sources main.cpp circle.cpp) add_executable(circle ${sources})
[mkdir build && cd build] cmake [..] make
README
or INSTALL
files or on the project's website