Function
Organization
//f1.cpp
#include <iostream>
using namespace std;
void f()
{
cout<<"Inside the function ..."<<endl;
}
int main(int argc, char* argv[])
{
f();
return 0;
}
//f2.cpp
#include <iostream>
using namespace std;
void f();
int main(int argc, char* argv[])
{
f();
return 0;
}
void f()
{
cout<<"Inside the function ..."<<endl;
}
//f3.h
#ifndef F3_H
#define F3_H
void f();
#endif
//util.cpp
#include <iostream>
#include "f3.h"
using namespace std;
void f()
{
cout<<"Inside the function ..."<<endl;
}
//f3.cpp
#include
#include "f3.h"
using namespace std;
int main(int argc, char* argv[])
{
f();
return 0;
}
Pass by value
#include <iostream>
using namespace std;
void increase(int n)
{
n++;
}
int main(int argc, char* argv[])
{
int n = 0;
increase(n);
cout<<n<<endl;
return 0;
}
Pass by reference
#include <iostream>
using namespace std;
void increase(int &n)
{
n++;
}
int main(int argc, char* argv[])
{
int n = 0;
increase(n);
cout<<n<<endl;
return 0;
}
Return value from function
#include <iostream>
using namespace std;
int increase(int n)
{
return ++n;
}
int main(int argc, char* argv[])
{
int n = 0;
n = increase(n);
cout<<n<<endl;
return 0;
}
Static local variables
#include <iostream>
using namespace std;
void showStatic();
int main(int argc, char *argv[])
{
for(int i = 0; i < 10; i++)
showStatic();
return 0;
}
void showStatic()
{
static int count = 0;
count++;
cout<<"Have been called "<<count<<" times ..."<<endl;
}
- Static local variables are not destroyed when a function returns.
- Exist for the lifetime of the program, even though their scope is only the function in which they are defined
Default arguments
#include <iostream>
using namespace std;
int showNum(int, int = 2, int = 3);
//int showNum(int, int = 2, int);//Illegal
int main(int argc, char *argv[])
{
showNum(10, 100, 1000);
showNum(10, 100);
showNum(10);
//showNum(, 10);//Illegal
return 0;
}
int showNum(int num1, int num2, int num3)
{
cout<<num1<<" "<<num2<<" "<<num3<<endl;
}
- The default arguments are listed in the funciton prototype, or in the function header, but not in both
- When a function uses a mixture of parameters with and without default arguments, the parameters with default arguments must be defined last
Variable number of parameters
#include <iostream>
#include <cstdarg>
#include <string>
using namespace std;
void display(string p, int n, ...);
int main(int argc, char *argv[])
{
display("Two parameters", 2, 10, 100);
display("Four parameters", 4, 1, 2, 3, 4);
return 0;
}
void display(string p, int n, ...)
{
va_list l;
va_start(l, n);
cout<<"n: "<<n<<endl;
for(int i = 0; i < n; i++)
cout<<va_arg(l, int)<<endl;
va_end(l);
}
To create a variadic function, an ellipsis (...) must be placed at the end if a parameter list
//C++ 11
//g++ -std=c++11 f10.cpp
#include <iostream>
#include <vector>
#include <initializer_list>
using namespace std;
void display(const initializer_list<int> &v)
{
for(int i = 0; i < v.size(); i++)
cout<<v.begin()[i]<<endl;//std::initializer_list does not have subscript operator
}
int main(int argc, char *argv[])
{
display({1, 2, 3, 4});
return 0;
}
Overloading functions
#include <iostream>
using namespace std;
void display(int n);
void display(int n1, int n2);
void display(double n);
void display(double n1, int n2);
int main(int argc, char *argv[])
{
int a = 1, b = 2;
double pi = 3.14;
display(a);
display(a, b);
display(pi);
display(pi, a);
return 0;
}
void display(int n) {cout<<n<<endl;}
void display(double n) {cout<<n<<endl;}
void display(int n1, int n2)
{
cout<<n1<<" "<<n2<<endl;
}
void display(double n1, int n2)
{
cout<<n1<<" "<<n2<<endl;
}
- Assign the same name to multiple functions, as long as their parameter lists are different
- Function signature
- the name of the function and the data types of the function's parameters in the proper order
- the function's return value is not part of the signature
- the number of parameters is also convenient for overloading
Recursive
#include <iostream>
int factorial(int);
int main(int argc, char *argv[])
{
std::cout<<factorial(10)<<std::endl;
return 0;
}
int factorial(int n)
{
if (n == 0)
return 1;
else
return n*factorial(n-1);
}
#include <iostream>
int gcd(int x, int y);
int main(int argc, char *argv[])
{
std::cout<<gcd(10, 2)<<std::endl;
std::cout<<gcd(2, 10)<<std::endl;
return 0;
}
int gcd(int x, int y)
{
if (x % y == 0)
return y;
else
return gcd(y, x % y);
}
Inline function
#include <iostream>
int doubleNum(int n);
int main(int argc, char *argv[])
{
std::cout<<doubleNum(10)<<std::endl;
return 0;
}
inline int doubleNum(int n)
{
return 2*n;
}
//util.cpp
#ifndef UTIL_H
#define UTIL_H
inline int doubleNum(int n)
{
return 2*n;
}
#endif
//main.cpp
#include <iostream>
#include "util.h"
int main(int argc, char *argv[])
{
std::cout<<doubleNum(10)<<std::endl;
return 0;
}
- Inine functions should be in header files
Template
//pass by value
#include <iostream>
template <class T>
T getSquare(T);
int main(int argc, char *argv[])
{
std::cout<<getSquare(10)<<std::endl;
return 0;
}
template <class T>
T getSquare(T n)
{
return n*n;
}
//pass by reference
#include <iostream>
template <class T>
void swap(T &, T &);
int main(int argc, char *argv[])
{
int a = 10, b = 100;
swap(a, b);
std::cout<<a<<" "<<b<<std::endl;
return 0;
}
template <class T>
void swap(T &a, T &b)
{
T temp;
temp = a;
a = b;
b = temp;
}
//multiple data types
#include <iostream>
template <class T1, class T2>
T1 mul(const T1 &, const T2 &);
int main(int argc, char *argv[])
{
int a = 10;
double b = 100.0;
std::cout<<mul(a, b)<<std::endl;
return 0;
}
template <class T1, class T2>
T1 mul(const T1 &a, const T2 &b)
{
return a*b;
}
#include <iostream>
template <class T>
void message();
int main(int argc, char *argv[])
{
message<int>();
return 0;
}
template <class T>
void message()
{
T a;
std::cin>>a;
std::cout<<a<<std::endl;
}
Explicitly select function template
- The template parameter T does not appear in the function's parameter list
- Forece the actualarguments to be promoted before the compiler deduces the template type
//deal with different data types
#include <iostream>
#include <typeinfo>
#include <string>
template <class T>
std::string getType(const T &n);
int main(int argc, char *argv[])
{
int a = 10;
double b = 3.14;
std::cout<<getType(a)<<std::endl;
std::cout<<getType(b)<<std::endl;
return 0;
}
template <class T>
std::string getType(const T & n)
{
char t = typeid(n).name()[0];
switch(t)
{
case 'i':
return "Integer";
break;
case 'd':
return "Double";
break;
default:
return "Unknown";
}
}
Put the template function in .h file
//util.h
#ifndef UTIL_H
#define UTIL_H
template <class T>
int getSize(T n)
{
return sizeof(n);
}
#endif
//main.cpp
#include <iostream>
#include "util.h"
int main(int argc, char *argv[])
{
int a = 0;
std::cout<<getSize(a)<<std::endl;
return 0;
}
Put the prototype of the template in .h file and the declaration of the template function in .cpp file
- Create a template prototype with specific data type
- Include both *.h file and *.cpp file
- include *.cpp file in *.h file
//util.h
#ifndef UTIL_H
#define UTIL_H
template <class T>
int getSize(T n);
#endif
//util.cpp
#include "util.h"
template <class T>
int getSize(T n)
{
return sizeof(n);
}
template int getSize<int>(int);
template int getSize<double>(double);
//main.cpp
#include <iostream>
#include "util.h"
int main(int argc, char *argv[])
{
double a = 0;
int b = 10;
std::cout<<getSize(a)<<std::endl;
std::cout<<getSize(b)<<std::endl;
return 0;
}
//util.h
#ifndef UTIL_H
#define UTIL_H
template <class T>
int getSize(T n);
#endif
//util.cpp
#include "util.h"
template <class T>
int getSize(T n)
{
return sizeof(n);
}
//main.cpp
#include <iostream>
#include "util.h"
#include "util.cpp"
int main(int argc, char *argv[])
{
double a = 0;
int b = 10;
std::cout<<getSize(a)<<std::endl;
std::cout<<getSize(b)<<std::endl;
return 0;
}
//util.h
#ifndef UTIL_H
#define UTIL_H
template <class T>
int getSize(T n);
#include "util.cpp"
#endif
//util.cpp
template <class T>
int getSize(T n)
{
return sizeof(n);
}
//main.cpp
#include <iostream>
#include "util.h"
int main(int argc, char *argv[])
{
double a = 0;
int b = 10;
std::cout<<getSize(a)<<std::endl;
std::cout<<getSize(b)<<std::endl;
return 0;
}
Reference
- Starting out with C++, Tony Gaddis
- isocpp.org