5.4 C++ 程式語言介紹


C++ Language

Class:

1
2
3
4
5
6
7
格式: class class_name
{
Constructor // 建構子
Destructor // 解構子
Attribute // 變數宣告
Operation // 函式定義
};

Object 宣告, 操作

class _ object;
操作:
object.att.
object.op.

  • Ex:
1
2
3
4
5
6
7
int main() {
Person P;
p.height = 180;
p.weight = 80;
p.walk(); // 印出 "Person walk"
return 0;
}

建構子 (Construtor)

  • Def:
    • 對 object 做 初始化 的動作
    • 於 object 產生時呼叫
    • Constructor name 和 class name 相同, 且 No return type
    • Constructor 可有很多個
  • Ex:
1
2
3
4
5
6
7
8
9
10
11
class A {
public:
//建構子
A() {
cout <<"con.A";
}
//解構子
~A() {
cout <<"del.A";
}
};

解構子 (Destructor)

  • Def:
    • 於 constructor 之前加上 “~”
    • Destructor 不接收參數 parameter list 為空
    • class 中 destructor 只會有一個
    • 於 object 被回收時呼叫
  • Ex:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Class A {
public:
A() {
cout <<"con.A";
}
~A() {
cout <<"del.A";
}
};

int main() {
A a1; a1 屬於 A
A a2;
return 0;
} // 結束前呼叫解構子 output?

變數種類

格式:
static _ type _ variable;
static int x;

  • Ex:
1
2
3
4
5
6
7
8
9
10
int main() {
fun();
fun();
return 0;
}
void fun() {
static int i = 20;
i++;
cout <<i;
}
  • Note:

    • 靜態變數存於靜態區塊中, “不會隨著所屬 block 結束而回收”, 於程式結束回收
    • 靜態變數之宣告只於第一次執行, 之後忽略之
  • Ex:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class A {
public:
int oid; // att
// 建構子
A(int i) {
oid = i;
}
//解構子
~A() {
cout <<oid;
}

int main() {
A a1(1); // 給建構子的參數
fun();
return 0;
}
void fun() {
A a2(2);
static A a3(3);
}
};

問 output is?

C++ 參考變數 Reference Variable

格式:
type **&**var = **被參考變數** (不可省略)
int &count = x; -> 替 x 取別名叫 count

注意事項:

  1. int count; (X) 替某人取綽號叫 count, 但某人不存在
  2. int &count = 3; (X) 常數(No mem space)

宣告時

int x; => call by value (一般)
int *x; => call by address (指標)
int &x; => call by reference (參數)

操作時

x=> 取內容
*x=> 取指標指向的值
&x=> 取所在 address

1
2
3
4
5
6
7
8
9
10
11
12
13
14
int main() {
int a = 10, b = 20;
swap(a, b);
cout <<a<<b;
return 0;
}

void swap(int x, int y) {
int &x = a;
int temp;
temp = x;
x = y;
y = temp;
}

Q:
1. a, b 呼叫 swap 後為何 No change? (call - by value)
2. How to modifiy?

C++ 的 Inheritance

  • Ex:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class A {
public: // 若改為 private, 此時 B會有 compile error
int x;
int y;
};
class B: Public A { //: 繼承
public:
B (inta, int b) {
x = a;
y = b;
}
void print() {
cout <<x<<y;
}
};
int main() {
B objB(2, 5);
objB.print();
return 0;
}

補充:繼承的存取權限

Overriding 覆載

  • 子類別將父類別的函式重新定義以符合自身所需

Overloading 多載

分為:

  1. function overloading

    1. 藉由接收多數串列的數量型別不同以達到共用相同的函式名稱

      • Ex1:
        • 對 user 而言較方便, 不需記過多的 function name
        • 對 programmer 而言命名 function 亦可簡化其原則
      1
      2
      3
      print(2); -> void print(int i)
      print(3.5); -> void print(double d)
      print("abc"); -> void print(char *s)
      • Ex2:
      1
      2
      3
      4
      5
      6
      class Person {
      public:
      Person() {...} // 建構子
      Person(int h) {...} // 建構子
      Person(inth, int w) {...} // 建構子 Overloading
      }
  2. operator overloading

    • Def: 藉由接收的運算元型別不同, 以達共用相同的運算子(operator)符號
    • 概念:
      • 3 + 5 => int + int
      • 2.3 + 5.5 => double + double
      • matrix + matrix

this vs super

  • 為 C++ 內建提供的物件指標
  • 其中:
    • this 會指向物件本身
    • super 會指向物件的 parent class
  • 說明:

物件指標

  1. 物件指標指向 attribute or operator
    ex: this -> i;
  2. (*物件指標).attribute or operator
    ex: (*this).i;
  • Ex: this.i … 錯誤 (成大)
    因為 “.” priority > “*”
    所以 括號不能拿掉
    (*(&(*this))).i; = (*this).i
    • 為從 address 拿回值
      & 為拿出 address

  • EX:
  • EX2 (政大):
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
void A(int V1, int V2)
{
int t = V2, V2 = V1 - 3, V1 = t + 3;
}

void pA(int *V1, int *V2)
{
int t = *V2;
*V2 = *V1 + 2;
*V1 = t - 4;
}

void rA(int &V1, int &V2)
{
int t = V2;
V2 = V1 + 4;
V1 = t - 5;
}

int main() {
int i = 1, j = 2;
cout <<i<<j<<"\n";
A(i, j); // call-by value
cout <<i<<j<<"\n";
pA(&i, &i); // call-by address
cout <<i<<j<<"\n";
rA(i, j); // call-by reference (取綽號, c++ 獨有)
cout <<i<<j<<"\n";
return 0
}

// Ans:
// 1 2
// 1 2
// -2 3
// -2 2

Polymorphism 多型

  • Def :
    • 多型主要是於執行時期利用動態繫結的方式來呼叫需執行的 function => 執行時才動態決定
    • C++ 中一般的函式呼叫於 compile time (state binding)已決定, 其呼叫位址 => 故無法達到多型
    • 在 C++ 中多加入一keyword virtual 來註明函式為 virtual function => 已達多型之效
  • 圖:
  1. 利用父類別型態 (須為指標或參數, 不能為一般變數)
  2. 接收不同子類別的物件
  3. 做相同的動作
  4. 引發不同的行為(同名異式)
  • Ex1:
  • NOTE: Polymorphism => Inheritance(:) + Overriding + Virtual function
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
// Virtual 一抽掉, 就永遠印出 An.walk
class Animal
{
public:
virtual void walk()
{
cout<<"An.walk";
}
};

class Person:public Animal
{
public:
virtual void walk() // 子類別的 virtual 可省略
{
cout<<"Person walk";
}
};

class Dog: public Animal
{
public:
virtual void walk()
{
cout<<"Dog walk";
}
};

int main () {
// 一定要指標或參考
Animzl *aPtr = 0; // 一開始是 0
Person p;
aPtr = &p; // 指標接收住址
aPtr-> walk(); // "Person" walk
Dog d;
aPtr = &d;
aPtr -> walk(); // "dog" walk
return 0;
}
  • Ex2: 政大

1
2
3
4
5
6
7
8
9
class Base
{
public:
virtual void iam()
{
cout<<"Base \n";
}
};

問:

  1. Derive two class from Base(繼承), and for each define iam() to write out the name of the class (override).
    Sol:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class D1: public Base
{
public:
virtual void iam()
{
cout<<"D1 \n";
}
};

class D2: public Base
{
public:
virtual void iam()
{
cout<<"D2 \n";
}
};
  1. Create objects of these classes(物件宣告), and call iam() for them(物件操作).
    Sol:
1
2
3
4
5
6
7
8
9
10
int main()
{
Base b;
D1 d1;
D2 d2;
b.iam();
d1.iam();
d2.iam();
return 0;
}
  1. Assign pointers to objects of the derived class to Base *pointers and call iam() through those pointers.
    Sol:
1
2
3
4
5
6
7
8
9
10
11
int main()
{
Base *b1, *b2;
D1 d1;
b1 = &d1;
b1 -> iam(); // 印出 "D1"
D2 d2;
b2 = &d2;
b2 -> iam(); // 印出 "D2"
return 0;
}