Advanced Concepts

Templates

Function templates

func_temp.cpp

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// function template

#include <iostream>
using namespace std;

template <class T>
T GetMax(T a, T b){
  T result;
  result = (a > b) ? a : b;
  return result;
}

int main(){
  int i1 = 10, i2 = 6;
  int i_comp;
  
  float l1 = 10.5, l2 = 6.5;
  float l_comp;
  
  i_comp = GetMax<int>(i1, i2);
  l_comp = GetMax<float>(l1, l2);

  cout << i_comp << endl;
  cout << l_comp << endl;
}

func_temp.cpp の実行結果は:

[cactus:~/code_c++/cpp_tuts]% ./func_temp
10
10.5

func_temp2.cpp

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// function template 2

#include <iostream>
using namespace std;

template <class T>
T GetMax(T a, T b){
  return (a > b ? a : b);
}

int main(){
  int i1 = 10, i2 = 6;
  int i_comp;
  
  float l1 = 10.5, l2 = 6.5;
  float l_comp;
  
  i_comp = GetMax(i1, i2);
  l_comp = GetMax(l1, l2);

  cout << i_comp << endl;
  cout << l_comp << endl;

  return 0;
}

func_temp2.cpp の実行結果は:

[cactus:~/code_c++/cpp_tuts]% ./func_temp2
10
10.5

Class templates

class_temp.cpp

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// class templates

#include <iostream>
using namespace std;

template <class T>
class mypair{
  T a;
  T b;
public:
  mypair(T fs, T se){
    a = fs;
    b = se;
  }
  T getmax();
};

template <class T>
T mypair<T>::getmax(){
  T retval;
  retval = (a > b? a : b);
  return retval;
}

int main(){
  mypair <int> myobject(100, 75);
  
  cout << myobject.getmax() << endl;

  return 0;
}

class_temp.cpp の実行結果は:

[cactus:~/code_c++/cpp_tuts]% ./class_temp
100

Template specialization

temp_spec.cpp

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
// template specialization

#include <iostream>
using namespace std;

// class template
template <class T>
class mycontainer{
  T element;
public:
  mycontainer(T arg){
    element = arg;
  }
  T increase(){
    return element++;
  }
};

// clas template specialization
template <>
class mycontainer <char>{
  char element;
public:
  mycontainer(char arg){
    element = arg;
  }
  char uppercase(){
    if( (element >= 'a') && (element <= 'z') )
      element += 'A' - 'a';
    return element;
  }
};

int main(){
  mycontainer<int> myint(7);
  mycontainer<char> mychar('j');

  cout << myint.increase() << endl;
  cout << mychar.uppercase() << endl;

  return 0;
}

temp_spec.cpp の実行結果は:

[cactus:~/code_c++/cpp_tuts]% ./temp_spec
7
J

Non-type parameters for templates

seqtemp.cpp

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// sequence template

#include <iostream>
using namespace std;

template <class T, int N>
class mysequence{
  T memblock[N];
public:
  void setmember(int x, T value);
  T getmember(int x);
};

template <class T, int N>
void mysequence<T, N>::setmember(int x, T value){
  memblock[x] = value;
}

template <class T, int N>
T mysequence<T, N>::getmember(int x){
  return memblock[x];
}

int main(){
  mysequence<int, 5> myints;
  mysequence<double, 5> myfloats;

  myints.setmember(0, 100); // index:0, value:100
  myfloats.setmember(3, 3.14159); // index:3, value: 3.14159

  cout << myints.getmember(0) << endl;
  cout << myfloats.getmember(3) << endl;

  return 0;
}

seqtemp.cpp の実行結果は:

[cactus:~/code_c++/cpp_tuts]% ./seqtemp
100
3.14159

Templates and multiple-file projects

Namespaces

Namespaces

namespaces.cpp

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
// namespaces

#include <iostream>
using namespace std;

namespace first{
  int var = 5;
}

namespace second{
  double var = 5.5;
}

int main(){
  cout << "first::var is " << first::var << endl;
  cout << "second::var is " << second::var << endl;
  
  return 0;
}

namespaces.cpp の実行結果は:

[cactus:~/code_c++/cpp_tuts]% ./namespaces
first::var is 5
second::var is 5.5

using

using.cpp

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// using

#include <iostream>
using namespace std;

namespace first{
  int x = 5;
  int y = 10;
}

namespace second{
  double x = 3.14;
  double y = 6.28;
}

int main(){
  using first::x;
  using second::y;

  cout << x << endl;
  cout << y << endl;
  cout << "first::y is " << first::y << endl;
  cout << "second::x is " << second::x << endl;
  
  return 0;
}

using.cpp の実行結果は:

[cactus:~/code_c++/cpp_tuts]% ./using
5
6.28
first::y is 10
second::x is 3.14

using2.cpp

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// using2

#include <iostream>
using namespace std;

namespace first{
  int x = 5;
  int y = 10;
}

namespace second{
  double x = 3.14;
  double y = 6.28;
}

int main(){
  using namespace first;

  cout << x << endl;
  cout << y << endl;
  
  cout << "second::x is " << second::x << endl;
  cout << "second::y is " << second::y << endl;
  
  return 0;
}

using2.cpp の実行結果は:

[cactus:~/code_c++/cpp_tuts]% ./using2
5
10
second::x is 3.14
second::y is 6.28

using3.cpp

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// using3 namespace example

#include <iostream>
using namespace std;

namespace first{
  int x = 5;
}

namespace second{
  double x = 3.14;
}

int main(){
  {
    using namespace first;
    cout << x << endl;
  }

  {
    using namespace second;
    cout << x << endl;
  }
  
  return 0;
}

using3.cpp の実行結果は:

[cactus:~/code_c++/cpp_tuts]% ./using3
5
3.14

Namespace alias

We can declare alternate namef for exisitng namespaces according following format:

namespace new_name = current_name;

Namespace std

All the files in the c++ standard library declare all of its entities within the std namespace. That is why we have generally included the using namespace std; statement in all programs that used any entity defined in iostream.

Exceptions

Exceptions

exception.cpp

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
// exception

#include <iostream>
using namespace std;

int main(){
  try{
    throw 20;
  }
  catch(int e){
    cout << "An exception occurred. Exception Nr. " << e << endl;
  }
}

exception.cpp の実行結果は:

[cactus:~/code_c++/cpp_tuts]% ./exception
An exception occurred. Exception Nr. 20

Standard exceptions

exception2.cpp

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
// standard exceptions

#include <iostream>
#include <exception>
using namespace std;

class myexception: public exception{
  virtual const char* what() const throw(){
    return "My exception happened";
  }
}myex;

int main(){
  try{
    throw myex;
  }
  catch(exception& e){
    cout << e.what() << endl;
  }
}

exception2.cpp の実行結果は:

[cactus:~/code_c++/cpp_tuts]% ./exception2
My exception happened

Type Casting

Explicit conversion

type_casting.cpp

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// class type-casting

#include <iostream>
using namespace std;

class CDummy{
  float i, j;
};

class CAddition{
  int x, y;
public:
  CAddition(int a, int b){
    x = a;
    y = b;
  }
  int result(){
    return x + y;
  }
};

int main(){
  CDummy d;
  CAddition *padd;

  padd = (CAddition *)&d;
  cout << padd->result() << endl;

  return 0;
}

type_casting.cpp の実行結果は:

[cactus:~/code_c++/cpp_tuts]% ./type_casting
0

dyna_cast.cpp

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// dynamic_cast

#include <iostream>
#include <exception>
using namespace std;

class CBase{
  virtual void dummy(){}
};

class CDerived: public CBase{
  int a;
};

int main(){
  try{
    CBase *pba = new CDerived;
    CBase *pbb = new CBase;
    CDerived *pd;

    pd = dynamic_cast<CDerived *>(pba);
    if(pd == 0)
      cout << "Null pointer on first type-cast" << endl;
    
    pd = dynamic_cast<CDerived *>(pbb);
    if(pd == 0)
      cout << "Null pointer on second type-cast" << endl;
  }catch(exception& e){
    cout << "Exception: " << e.what();
  }
  
  return 0;
}

dyna_cast.cpp の実行結果は:

[cactus:~/code_c++/cpp_tuts]% ./dyna_cast
Null pointer on second type-cast

const_cast

const_cast.cpp

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
// const_cast

#include <iostream>
#include <exception>
using namespace std;

void print(char *str){
  cout << str << endl;
}

int main(){
  const char *c = "sample text";

  print( const_cast<char *>(c) );
  
  return 0;
}

const_cast.cpp の実行結果は:

[cactus:~/code_c++/cpp_tuts]% ./const_cast
sample text

typeid

typeid.cpp

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
// typeid

#include <iostream>
#include <typeinfo>
using namespace std;

int main(){
  int *a, b;
  a = 0;
  b = 0;
  if( typeid(a) != typeid(b) ){
    cout << "a and b are different types:" << endl;
    cout << "a is: " << typeid(a).name() << endl;
    cout << "b is: " << typeid(b).name() << endl;
  }
  
  return 0;
}

typeid.cpp の実行結果は:

[cactus:~/code_c++/cpp_tuts]% ./typeid
a and b are different types:
a is: Pi
b is: i

typeid2.cpp

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// typeid, polymorphic class

#include <iostream>
#include <typeinfo>
#include <exception>
using namespace std;

class CBase{
  virtual void f(){}
};

class CDerived: public CBase{};

int main(){
  try{
    CBase *a = new CBase;
    CBase *b = new CDerived;

    cout << "a is: " << typeid(a).name() << endl;
    cout << "b is: " << typeid(b).name() << endl;
    
    cout << "*a is: " << typeid(*a).name() << endl;
    cout << "*b is: " << typeid(*b).name() << endl;
  }catch(exception& e){
    cout << "Exception: " << e.what() << endl;
  }
  
  return 0;
}

typeid2.cpp の実行結果は:

[cactus:~/code_c++/cpp_tuts]% ./typeid2
a is: P5CBase
b is: P5CBase
*a is: 5CBase
*b is: 8CDerived

Preprocessor directives

macro definitions (#define, #undef)

macro.cpp

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
// function macro
#include <iostream>
using namespace std;

#define getmax(a, b) ( (a) > (b) ? (a) : (b) )

int main(){
  int x = 5;
  int y;

  y = getmax(x, 2);
  
  cout << y << endl;
  cout << getmax(7, x) << endl;
  cout << getmax(7.2, 4.3) << endl;
  cout << getmax(7.2, 8) << endl;

  return 0;
}

macro.cpp の実行結果は:

[cactus:~/code_c++/cpp_tuts]% ./macro
5
7
7.2
8

Predefined macro names

predefined.cpp

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
// standard macro names
#include <iostream>
using namespace std;

int main(){

  cout << "This is the line number: " << __LINE__ << endl;
  cout << "of file: " << __FILE__ << endl;
  cout << "Its compilation began: " << __DATE__ << endl;
  cout << "at: " << __TIME__ << endl;
  cout << "The compiler gives a __cplusplus value of: " << __cplusplus << endl;

  return 0;
}

predefined.cpp の実行結果は:

[cactus:~/code_c++/cpp_tuts]% ./predefined
This is the line number: 7
of file: predefined.cpp
Its compilation began: Sep 22 2010
at: 19:35:27
The compiler gives a __cplusplus value of: 1

Table Of Contents

Previous topic

Object Oriented Programming

Next topic

C++ Standard Library