Object Oriented Programming

Classes (I)

Class are generally declared using the keyword class, with the format:

class class_name{
  access_specifier_1:
    member1;
  access_specifier_2:
    member2;
  ...
} object_names;

An access specifier is one the following three keywords: private, public or protected:

private members of a class are accessible only from within other members of the same class or from their friends.

protected members are accessible from members of their same class and from their friends, but also from members of their derived classes.

Finally, public members are accessible from anywhere where the object is visible.

By default, all members of a class declard with class keyword have private access for all its members. Therefore, any member that is declared before one other class specifier automatically has private access. For example:

class CRectangle{
  int x, y;
public:
  void set_values(int, int);
  int area(void);
}rect;

class.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 example

#include <iostream>
using namespace std;

class CRectangle{
public:
  int x, y; // デフォルトの場合は, 変数 x, y は private タイプ
public:
  void set_values(int a, int b);
  int area(){
    return x*y;
  }
}; // セミコロンを忘れないこと

void CRectangle::set_values(int a, int b){
  x = a;
  y = b;
}
  
int main(void){

  CRectangle rect;
  rect.set_values(3, 4);
  
  cout << "x = " << rect.x  << " y = " << rect.y << endl;
  cout << "area: " << rect.area() << endl;
  
  return 0;

}

class.cpp の実行結果は:

[cactus:~/code_c++/cpp_tuts]% ./class
x = 3 y = 4
area: 12

class2.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
// example: one class, two objects

#include <iostream>
using namespace std;

class CRectangle{
  int x, y; // デフォルトの場合は, 変数 x, y は private タイプ
public:
  void set_values(int a, int b);
  int area(){
    return x*y;
  }
}; // セミコロンを忘れないこと

void CRectangle::set_values(int a, int b){
  x = a;
  y = b;
}
  
int main(void){

  CRectangle rect_a;
  CRectangle rect_b;
  
  rect_a.set_values(3, 4);
  rect_b.set_values(5, 6);
  
  cout << "rect_a area is: " << rect_a.area() << endl;
  cout << "rect_b area is: " << rect_b.area() << endl;
  
  return 0;

}

class2.cpp の実行結果は:

[cactus:~/code_c++/cpp_tuts]% ./class2
rect_a area is: 12
rect_b area is: 30

Constructors and destructors

Object generally need to initialize variables or assign dynamic memory during their process of creation to become operative an to avoid returning unexpected values during theri execution.

We are going to implement CRectangle including a constructor:

constructor.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
// example: class constructor

#include <iostream>
using namespace std;

class CRectangle{
  int width, height;
public:
  CRectangle(int, int);
  int area(){
    return width * height;
  }
}; // セミコロンを忘れないこと

// Constructor of class CRectangle
CRectangle::CRectangle(int a, int b){
  width = a;
  height = b;
}
  
int main(void){

  CRectangle rect_a(4, 5);
  CRectangle rect_b(6, 7);
  
  cout << "rect_a area is: " << rect_a.area() << endl;
  cout << "rect_b area is: " << rect_b.area() << endl;
  
  return 0;

}

constructor.cpp の実行結果は:

[cactus:~/code_c++/cpp_tuts]% ./constructor
rect_a area is: 20
rect_b area is: 42

Constructors cannot be called explicitly as if they were regular member functions. They are only executed when a new object of that class is created.

You can also see how neither the constructor prototype declaration (within the class) nor the latter constructor definition include a return value; not even void.

The destructor fulfills the opposite functionality. It is automatically called when an object is destroyed, either because its scope of existence has finished (for example, if it was defined as a local object within a function and the function ends) or because it is an object dynamically assigned and it is released using the operator delete.

The destructor must have the same name as the class, but preceded with a tilde sign (~) and it must also return no value.

The use of destructors is especially suitable when an object assigns dynamic memory during its lifetime and at the moment of being destroyed we want to release the memory that the object was allocated.

destructor.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
// example on constructors and destructors

#include <iostream>
using namespace std;

class CRectangle{
  int *width, *height;
public:
  CRectangle(int, int);
  ~CRectangle(void);
  int area(void){
    return (*width) * (*height);
  }
}; // セミコロンを忘れないこと

// Constructor of class CRectangle
CRectangle::CRectangle(int a, int b){
  width = new int;
  height = new int;
  *width = a;
  *height = b;
}

// Destructor of class CRectangle
CRectangle::~CRectangle(void){
  delete width;
  delete height;
}
  
int main(void){

  CRectangle rect_a(4, 5);
  CRectangle rect_b(6, 7);
  
  cout << "rect_a area is: " << rect_a.area() << endl;
  cout << "rect_b area is: " << rect_b.area() << endl;
  
  return 0;

}

destructor.cpp の実行結果は:

[cactus:~/code_c++/cpp_tuts]% ./destructor
rect_a area is: 20
rect_b area is: 42

Overloading Constructors

Like any other function, a constructor can also be overloaded with more than one function that have the same name but different types or number of parameters. Remember that for overloaded functions the compiler will call the one whose parameters match the arguments used in the function call. In the case of constructors, which are automatically called when an object is created, the one executes is the one thant matches the argiments passed on the object declaration:

overloading.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
// overloading class constructors

#include <iostream>
using namespace std;

class CRectangle{
  int width, height;
public:
  CRectangle();
  CRectangle(int, int);
  int area(){
    return width * height;
  }
}; // セミコロンを忘れないこと

CRectangle::CRectangle(){
  width = 5;
  height = 5;
}

CRectangle::CRectangle(int a, int b){
  width = a;
  height = b;
}

int main(void){

  CRectangle rect_a; // () 括弧を使わないこと
  CRectangle rect_b(6, 6);
  
  cout << "rect_a area is: " << rect_a.area() << endl;
  cout << "rect_b area is: " << rect_b.area() << endl;
  
  return 0;

}

overloading.cpp の実行結果は:

[cactus:~/code_c++/cpp_tuts]% ./overloading
rect_a area is: 25
rect_b area is: 36

Pointers to classes

p_to_class.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
43
44
// pointer to classes example

#include <iostream>
using namespace std;

class CRectangle{
  int width, height;
public:
  void set_values(int, int);
  int area(void){
    return width * height;
  }
}; // セミコロンを忘れないこと

void CRectangle::set_values(int a, int b){
  width = a;
  height = b;
}

int main(void){

  CRectangle a;
  CRectangle *b;
  CRectangle *c;
  CRectangle *d = new CRectangle[2];

  b = new CRectangle;
  c = &a;

  a.set_values(1, 2);
  b->set_values(3, 4);
  d->set_values(5, 6); // d[0]
  d[1].set_values(7, 8);
  
  cout << "a area: " << a.area() << endl;
  cout << "*b area: " << b->area() << endl;
  cout << "*c area: " << c->area() << endl; // a と同じ
  cout << "d[0] area: " << d[0].area() << endl;
  cout << "d[1] area: " << d[1].area() << endl;
  
  
  return 0;

}

p_to_class.cpp の実行結果は:

[cactus:~/code_c++/cpp_tuts]% ./p_to_class
a area: 2
*b area: 12
*c area: 2
d[0] area: 30
d[1] area: 56

Next you have a summary on how can you read some pointer and class operators that appear in the previous example:

_images/p_to_class.png

Classes (II)

Overloading operators

over-op.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
43
44
45
46
// vectors: overloading operators example

#include <iostream>
using namespace std;

class CVector{
public:
  int x, y;
  CVector(){
    x = 0;
    y = 0;
  }; // {} を忘れないこと
  CVector(int, int); // function name CVector (constructor)
  CVector operator+(CVector); // function returns a CVector
}; // セミコロンを忘れないこと

CVector::CVector(int a, int b){
  x = a;
  y = b;
}

CVector CVector::operator+(CVector param){
  CVector temp;
  temp.x = x + param.x;
  temp.y = y + param.y;
  return temp;
}

int main(void){

  CVector a(4, 5);
  CVector b(5, 4);
  CVector c;
  CVector d;
  
  c = a + b;
  d = a;
  
  // 下の書き方にしても okay
  // c = a.operator+(b);

  cout << c.x << ", " << c.y << endl;
  cout << d.x << ", " << d.y << endl;
  
  return 0;
}

over-op.cpp の実行結果は:

[cactus:~/code_c++/cpp_tuts]% ./over-op
9, 9
4, 5

The keyword this

this.cpp

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

#include <iostream>
using namespace std;

class CDummy{
public:
  int isitme(CDummy& param);
}; // セミコロンを忘れないこと

int CDummy::isitme(CDummy& param){
  if(&param == this) return true;
  else return false;
}

int main(void){
  CDummy a;
  CDummy *b = &a;

  if(b->isitme(a))
    cout << "yes, &a is b" << endl;
  return 0;
}

this.cpp の実行結果は:

[cactus:~/code_c++/cpp_tuts]% ./this
yes, &a is b

Static members

A class can contain static members, either data or functions.

Static data members of a class are also known as “class variables”, because there is only one unique value for all the objects of that same class. Their content is not different from one object of this class to another.

For example, it may be used for a variable within a class that can contain a counter with the number of objects of that class that are currently allocated, as if the following example:

static.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
43
44
45
// this

#include <iostream>
using namespace std;

class CDummy{
public:
  static int n;
  CDummy(){
    n++;
  };
  ~CDummy(){
    n--;
  };
}; // セミコロンを忘れないこと

int CDummy::n = 0;

int main(void){
  
  cout << "CDummy::n = " << CDummy::n << endl; // n = 0
  
  CDummy a;
  cout << "CDummy::n = " << CDummy::n << endl; // n = 0 + 1 = 1
  
  CDummy b[2];
  cout << "CDummy::n = " << CDummy::n << endl; // n = 1 + 2 = 3
  
  CDummy c[3];
  cout << "CDummy::n = " << CDummy::n << endl; // n = 3 + 3 = 6
  
  CDummy *d = new CDummy;
  cout << "CDummy::n = " << CDummy::n << endl; // n = 6 + 1 = 7
  
  CDummy *e = new CDummy;
  cout << "CDummy::n = " << CDummy::n << endl; // n = 7 + 1 = 8

  delete d;
  cout << "CDummy::n = " << CDummy::n << endl; // n = 8 - 1 = 7

  delete e;
  cout << "CDummy::n = " << CDummy::n << endl; // n = 7 - 1 = 6

  return 0;
}

static.cpp の実行結果は:

[cactus:~/code_c++/cpp_tuts]% ./static
CDummy::n = 0
CDummy::n = 1
CDummy::n = 3
CDummy::n = 6
CDummy::n = 7
CDummy::n = 8
CDummy::n = 7
CDummy::n = 6

Friendship and inheritance

Friend functions

In principle, private and proctected members of a class cannot be accessed from outside the same class in which they are declared. However, this rule does not affect friends.

Friends are functions or classes declared with the friend keyword.

If we want to declare an external function as friend of a class, thus allowing this function to have access to the private and protected members of this class, we do it by declaring a prototype of this external function within the class, and preceding it with the keyword friend:

friend.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
// friend function

#include <iostream>
using namespace std;

class CRectangle{
  int width, height;
public:
  void set_values(int, int);
  int area(){
    return width * height;
  }
  friend CRectangle duplicate(CRectangle); // friend keyword を付けること
};

void CRectangle::set_values(int a, int b){
  width = a;
  height = b;
}

CRectangle duplicate(CRectangle rectparam){
  CRectangle rectres;
  rectres.width = rectparam.width * 2;
  rectres.height = rectparam.height * 2;
  return rectres;
}

int main(void){
  CRectangle rect_a, rect_b;
  
  rect_a.set_values(2, 3);
  rect_b = duplicate(rect_a);

  cout << rect_b.area() << endl;

  return 0;
}

friend.cpp の実行結果は:

[cactus:~/code_c++/cpp_tuts]% ./friend
24

The duplicate function is a friend of CRectangle. From within that function we have been able to access the members width and height of different objects of type CRectangle, which are private member. Notice that neither in the declaration of duplicate() nor in its later use in main() have we considered duplicate a member of class CRectangle. It isn’t! It simply has access to its private and protected members without being a member.

The friend functions can serve, for example, to conduct operations between two different classes. Generally, the use of friend functions is out of an object-oriented programming methodology, so whenever possible it is better to use members of the same class to perform operations with them. Such as in the previous example, it would have been shorter to integrate duplicate() within the class CRectangle.

friend1.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
/*
 フレンド関数
 クラスの private メンバにアクセスできるのは原則として, クラスのメンバ関数のみですが,
 friend キーワードを付けることで 外部の関数から private メンバへアクセスできるように
 なる.
*/

#include <iostream>
using namespace std;

class Sample{
  int mi_sample;
  
public:
  Sample(){
    mi_sample = 0;
  }
  
  int GetVal(){
    return mi_sample;
  }
  
  friend void add(Sample& obj); // フレンド関数プロトタイプ宣言
};

void add(Sample& obj){
  obj.mi_sample++;
}

int main(void){
  Sample sample_a;
  
  cout << sample_a.GetVal() << endl; // mi_sample = 0
  add(sample_a); // フレンド関数
  cout << sample_a.GetVal() << endl; // mi_sample = 1

  return 0;
}

friend1.cpp の実行結果は:

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

Friend classes

friendclass.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
// friend class

#include <iostream>
using namespace std;

class CSquare;

class CRectangle{
  int width, height;
public:
  int area(){
    return width * height;
  }
  void convert(CSquare a);
};

class CSquare{
private:
  int side;
public:
  void set_side(int a){
    side = a;
  }
  friend class CRectangle;
};

void CRectangle::convert(CSquare a){
  width = a.side;
  height = a.side;
}

int main(void){
  CSquare sqr;
  CRectangle rect;

  sqr.set_side(4);
  rect.convert(sqr);
  cout << "rect area is: " << rect.area() << endl;

  return 0;
}

friendclass.cpp の実行結果は:

[cactus:~/code_c++/cpp_tuts]% ./friendclass
rect area is: 16

Inheritance between classes

inheritance.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
43
44
45
46
47
48
49
// derived classes

#include <iostream>
using namespace std;

class CPolygon{
protected:
  int width, height;
public:
  void set_values(int a, int b){
    width = a;
    height = b;
  }
};

/*
 子クラス CRectangle は親クラス CPolygon のメソッド set_values を継承する同時に,
 新しいメッソド area を作っておく
*/
class CRectangle: public CPolygon{
public:
  int area(){
    return width * height;
  }
};

/*
 子クラス CTriangle は親クラス CPolygon のメソッド set_values を継承する同時に,
 新しいメッソド area を作っておく
*/
class CTriangle: public CPolygon{
public:
  int area(){
    return (width * height) / 2;
  }
};

int main(void){
  CRectangle rect;
  CTriangle trgl;

  rect.set_values(4, 5);
  trgl.set_values(4, 5);

  cout << "rect area: " << rect.area() << endl;
  cout << "trgl area: " << trgl.area() << endl;

  return 0;
}

inheritance.cpp の実行結果は:

[cactus:~/code_c++/cpp_tuts]% ./inheritance
rect area: 20
trgl area: 10

What is inherited from the base class?

inheritance1.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
// constructors and derived classes

#include <iostream>
using namespace std;

class Mother{
public:
  Mother(){
    cout << "Mother: no parameters" << endl;
  }
  Mother(int a){
    cout << "Mother: int parameters" << endl;
  }
};

class Daughter: public Mother{
public:
  Daughter(int a){ // nothing specified: call default
    cout << "Daughter: int parameters\n" << endl;
  }
};

class Son: public Mother{
public:
  Son(int a): Mother(a){ // constructor specifed: call this
    cout << "Son: int parameters" << endl;
  }
};

int main(void){
  Daughter sasa(0);
  Son jimmy(0);
  
  return 0;
}

inheritance1.cpp の実行結果は:

[cactus:~/code_c++/cpp_tuts]% ./inheritance
rect area: 20
trgl area: 10

Multiple inheritance

inheritance2.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
43
44
45
46
47
48
49
50
// multiple inheritance

#include <iostream>
using namespace std;

class CPolygon{
protected:
  int width, height;
public:
  void set_values(int a, int b){
    width = a;
    height = b;
  }
};

class COutput{
public:
  void output(int i);
};

void COutput::output(int i){
  cout << i << endl;
}

class CRectangle: public CPolygon, public COutput{
public:
  int area(){
    return width * height;
  }
};

class CTriangle: public CPolygon, public COutput{
public:
  int area(){
    return (width * height) / 2;
  }
};

int main(void){
  CRectangle rect;
  CTriangle trgl;

  rect.set_values(4, 5);
  trgl.set_values(4, 5);

  rect.output( rect.area() );
  trgl.output( trgl.area() );
    
  return 0;
}

inheritance2.cpp の実行結果は:

[cactus:~/code_c++/cpp_tuts]% ./inheritance2
20
10

Polymorphism

Pointers to base class

polymorphism1.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
43
// pointers to base class

#include <iostream>
using namespace std;

class CPolygon{
protected:
  int width, height;
public:
  void set_values(int a, int b){
    width = a;
    height = b;
  }
};

class CRectangle: public CPolygon{
public:
  int area(){
    return width * height;
  }
};

class CTriangle: public CPolygon{
public:
  int area(){
    return (width * height) / 2;
  }
};

int main(){
  CRectangle rect;
  CTriangle trgl;
  CPolygon *ppoly1 = &rect;
  CPolygon *ppoly2 = &trgl;

  ppoly1->set_values(4, 5);
  ppoly2->set_values(4, 5);

  cout << "rect.area() is: " << rect.area() << endl;
  cout << "trgl.area() is: " << trgl.area() << endl;
  
  return 0;
}

polymorphism1.cpp の実行結果は:

[cactus:~/code_c++/cpp_tuts]% ./polymorphism1
rect.area() is: 20
trgl.area() is: 10

Virtual members

vr_members.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
43
44
45
46
47
48
49
50
51
// virtual members

#include <iostream>
using namespace std;

class CPolygon{
protected:
  int width, height;
public:
  void set_values(int a, int b){
    width = a;
    height = b;
  }
  virtual int area(){
    return 0;
  }
};

class CRectangle: public CPolygon{
public:
  int area(){
    return width * height;
  }
};

class CTriangle: public CPolygon{
public:
  int area(){
    return (width * height) / 2;
  }
};

int main(){
  CRectangle rect;
  CTriangle trgl;
  CPolygon poly;
  
  CPolygon *ppoly1 = &rect;
  CPolygon *ppoly2 = &trgl;
  CPolygon *ppoly3 = &poly;

  ppoly1->set_values(4, 5);
  ppoly2->set_values(4, 5);
  ppoly3->set_values(4, 5);

  cout << "ppoly1->area() is: " << ppoly1->area() << endl;
  cout << "ppoly2->area() is: " << ppoly2->area() << endl;
  cout << "ppoly3->area() is: " << ppoly3->area() << endl;
  
  return 0;
}

vr_members.cpp の実行結果は:

[cactus:~/code_c++/cpp_tuts]% ./vr_members
ppoly1->area() is: 20
ppoly2->area() is: 10
ppoly3->area() is: 0

Abstract base classes

abstract.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
43
44
45
46
47
// abstract base class

#include <iostream>
using namespace std;

class CPolygon{
protected:
  int width, height;
public:
  void set_values(int a, int b){
    width = a;
    height = b;
  }
  virtual int area(){
    return 0;
  }
};

class CRectangle: public CPolygon{
public:
  int area(){
    return width * height;
  }
};

class CTriangle: public CPolygon{
public:
  int area(){
    return (width * height) / 2;
  }
};

int main(){
  CRectangle rect;
  CTriangle trgl;
  
  CPolygon *ppoly1 = &rect;
  CPolygon *ppoly2 = &trgl;

  ppoly1->set_values(4, 5);
  ppoly2->set_values(4, 5);

  cout << "ppoly1->area() is: " << ppoly1->area() << endl;
  cout << "ppoly2->area() is: " << ppoly2->area() << endl;
  
  return 0;
}

abstract.cpp の実行結果は:

[cactus:~/code_c++/cpp_tuts]% ./abstract
ppoly1->area() is: 20
ppoly2->area() is: 10

abstract2.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
43
44
45
46
47
48
49
50
51
// pure virtual members can be called
// from the abstract base class

#include <iostream>
using namespace std;

class CPolygon{
protected:
  int width, height;
public:
  void set_values(int a, int b){
    width = a;
    height = b;
  }
  virtual int area(void){
    return 0;
  }
  void printarea(void){
    cout << this->area() << endl;
  }
};

class CRectangle: public CPolygon{
public:
  int area(){
    return width * height;
  }
};

class CTriangle: public CPolygon{
public:
  int area(){
    return (width * height) / 2;
  }
};

int main(){
  CRectangle rect;
  CTriangle trgl;
  
  CPolygon *ppoly1 = &rect;
  CPolygon *ppoly2 = &trgl;

  ppoly1->set_values(4, 5);
  ppoly2->set_values(4, 5);

  ppoly1->printarea();
  ppoly2->printarea();
    
  return 0;
}

abstract2.cpp の実行結果は:

[cactus:~/code_c++/cpp_tuts]% ./abstract2
20
10

dyna-poly.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
43
44
45
46
47
48
49
50
51
// dynamic allocation and polymorphism

#include <iostream>
using namespace std;

class CPolygon{
protected:
  int width, height;
public:
  void set_values(int a, int b){
    width = a;
    height = b;
  }
  virtual int area(void){
    return 0;
  }
  void printarea(void){
    cout << this->area() << endl;
  }
};

class CRectangle: public CPolygon{
public:
  int area(){
    return width * height;
  }
};

class CTriangle: public CPolygon{
public:
  int area(){
    return (width * height) / 2;
  }
};

int main(){
  
  CPolygon *ppoly1 = new CRectangle;
  CPolygon *ppoly2 = new CTriangle;

  ppoly1->set_values(4, 5);
  ppoly2->set_values(4, 5);

  ppoly1->printarea();
  ppoly2->printarea();

  delete ppoly1;
  delete ppoly2;
    
  return 0;
}

dyna-poly.cpp の実行結果は:

[cactus:~/code_c++/cpp_tuts]% ./dyna-poly
20
10

super.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
/* g++ -Wall -o super super.cpp */

#include <iostream>

using namespace std;

class Super{
public: Super(){
  cout << "Super() が呼ばれた." << endl;
}
public: Super(int aNumber){
  cout << "Super(int a Number) が呼ばれた." << endl;
}
public: virtual ~Super(){
  cout << "~Super() が呼ばれた."  << endl;
}
};

class Sub : public Super{
public: Sub() : Super(){
  cout << "Sub() が呼ばれた." << endl;
}
public: Sub(int aNumber) : Super(aNumber){
  cout << "Sub(int aNumber) が呼ばれた." << endl;
}
public: ~Sub(){
  cout << "~Sub() が呼ばれた." << endl;
}
};

int main(void){
  Super *tInstance;
  tInstance = new Sub();
  delete tInstance;

  tInstance = new Sub(10);
  delete tInstance;
  
  return 0;
}

super.cpp の実行結果は:

[cactus:~/code_c++/cpp_tuts]% ./super
Super() が呼ばれた.
Sub() が呼ばれた.
~Sub() が呼ばれた.
~Super() が呼ばれた.
Super(int a Number) が呼ばれた.
Sub(int aNumber) が呼ばれた.
~Sub() が呼ばれた.
~Super() が呼ばれた.

Table Of Contents

Previous topic

Compound Data Types

Next topic

Advanced Concepts