SKCONAN

การใช้งานคลาสใน CPP แบบเบื้องต้น

May 11, 2019

คลาส คืออะไร ???

class คือ template สำหรับการสร้าง objects โดยการเขียน class นั้น ถ้าให้เข้าใจง่ายๆ class ก็คือ การเอา function กับ variable ที่มีการใช้งานร่วมกัน และมีการทำงานซ้ำๆกันบ่อยๆ เพื่อให้นำไปใช้งานได้ง่ายขึ้น

ตัวอย่าง การสร้างเกมส์ต่อสู้ ถ้าเราต้องเก็บสถานะของตัวละคร หรือสร้าง function ของตัวละครแต่ละตัวแยกกัน มันก็จะมีความยุ่งยากในการเรียกใช้งานตัวแปร หรือ function เช่น แมวสู้กับเสือ เมื่อแมวจะโจมตีก็ต้องไปเรียก catattack() เมื่อเสื้อจะโจมตีก็ไปเรียก tigerattack() หรือถ้าแมวเลือดลดก็ต้องเข้าไปแก้ไขตัวแปร cat_blood จะง่ายกว่ามั้ยถ้าเราทำเป็น class

การสร้าง class

ตัวอย่าง class Player จะสร้างตัวแปร blood และ function attack

#include <iostream>
#include <string>

using namespace std;

class Player
{
    public:
        string name;
        int blood;
        void attack(Player p, int damage){
            p.blood -= 5;
        }        
};

int main()
{
    Player cat;
    cat.blood = 10;
    cout << cat.blood << endl;
    return 0;
}

ผลลัพธ์ที่ได้

10

เท่านี้เราก็จะได้ player ที่เป็นแมว ซึ่งมีเลือด 10 ต่อมากเราจะลองเปลี่ยนตัวแปร blood เป็น private เพราะ ว่าเราไม่ต้องการให้มีการแก้ไขจากภายนอก class ตอนนี้ทุกคนอาจจะสงสัยว่า private public คืออะไร เรามาดูกัน

ตัวกำหนดการเข้าถึง (Access specifier)

class จะมีตัวที่บอกว่าตัวแปร (variable) หรือฟังก์ชั่นที่สร้างขึ้นมานั้น สามารถเข้าถึง หรือเรียกใช้ได้จากที่ไหนบ้าง

แล้ว Public Private และ Protected ต่างกันยังไง ???

public private protected
เข้าถึงจากในคลาสตัวเองได้ / / /
เข้าถึงจากภายนอกได้ / X X
สามารสืบทอดได้ / X /

ทีนี้เราก็มาเปลี่ยนตัวแปร blood ให้เป็น private กัน

#include <iostream>
#include <string>

using namespace std;

class Player
{
    public:
        string name;
        void attack(Player p, int damage){
            p.blood -= 5;
        }
    
    private:
        int blood;
};

int main()
{
    Player cat;
    cat.blood = 10;
    cout << cat.blood << endl;
    return 0;
}


ผลลัพธ์ที่ได้

\player_class.cpp: In function 'int main()':
\player_class.cpp:15:13: error: 'int Player::blood' is private
         int blood;
             ^
\player_class.cpp:21:8: error: within this context
     cat.blood = 10;
        ^
\player_class.cpp:15:13: error: 'int Player::blood' is private
         int blood;
             ^
\player_class.cpp:22:16: error: within this context
     cout << cat.blood << endl;
                ^

ในตอนที่เรา Complie มันก็จะฟ้อง error ขึ้นมาว่าตรง cat.blood มันผิดนะ เพราะ blood เป็น private

แล้วถ้าตัวแปร blood เป็น private แล้วถ้าเราอยากลด หรือเพิ่มเลือดให้ Player แต่ละคนเราจะทำยังไงละ

วิธีแก้ก็คือ ก็สร้าง function blood_update(int b) ที่ใช้สำหรับลด หรือเพิ่มโดยกำหนดสิทธิการเข้าถึงเป็นแบบ public เพื่อให้สามารถเรียก function blood ผ่าน Object ได้ (เข้าถึงจากภายนอก class ได้) มาลองเขียนโค้ดกัน

#include <iostream>
#include <string>

using namespace std;

class Player
{
    public:
        string name;
        void attack(Player p, int damage){
            p.blood_update(-5);
        }

        void blood_update(int b){
            blood += b;
            cout << "blood: " << blood << endl;
        }

    private:
        int blood=0;
};

int main()
{
    Player cat;
    cat.blood_update(10);
    return 0;
}

ผลลัพธ์ที่ได้

blood: 10

ปล. ใครขึ้น warning ไม่เป็นไรนะ อาจจะเป็นเพราะ version ของตัว g++

แค่นี้เราก็สามารถแก้ไขค่า blood ได้แล้ว ทีนี้เราอยากให้ blood เริ่มต้นของ player ทุกตัวมีค่า 100 เราจะทำไงดีนะ ซึ่งคำตอบอยู่ข้างล่างแล้ว คือ เราจะใช้ Constructor นั้นเอง

Constructor คืออะไร

มันคือสิ่งที่มี ชื่อเดียว กับคลาส แล้วก็อยู่ในคลาส โดยเจ้าตัว Constructor จะถูกเรียกทันทีหลังจากที่มีการสร้างคลาส โดยปกติแล้วจะใช้ในการกำหนดค่าตัวแปรเริ่มต้น อะมาลองดูโค้ดกัน

#include <iostream>
#include <string>

using namespace std;

class Player
{
    public:
        string name;
        void attack(Player p, int damage){
            p.blood_update(-5);
        }

        void blood_update(int b){
            blood += b;
            cout << "blood: " << blood << endl;
        }

        Player(){
            blood = 100;
        }

    private:
        int blood;
};

int main()
{
    Player cat;
    cat.blood_update(10);
    return 0;
}

ผลลัพธ์ที่ได้

blood: 110

จากโค้ดเราลองสร้าง Contructor ที่มีกำหนดค่า blood เริ่มต้นเป็น 100

ต่อมาลองสร้าง Contructor แบบรับค่าเริ่มต้นกันบ้าง โดยเราสามารถเพิ่ม Constructor แบบใหม่เข้าไปได้เลย ซึ่งการที่เรามีหลายๆ contructor มันจะทำงานเหมือนกับ overloading function

#include <iostream>
#include <string>

using namespace std;

class Player
{
    public:
        string name;
        void attack(Player p, int damage){
            p.blood_update(-5);
        }

        void blood_update(int b){
            blood += b;
            cout << "blood: " << blood << endl;
        }

        Player(){
            blood = 100;
        }

        Player(string n){
            name = n;
        }

    private:
        int blood;
};

int main()
{
    Player cat("Tom");
    cout << "name:" << cat.name << endl;
    cat.blood_update(10);
    return 0;
}

ผลลัพธ์ที่ได้

name:Tom
blood: 12410234

จะสังเกตว่า cat จะมีการกำหนดชื่อ แต่ไม่มีการกำหนดค่าให้ blood ค่า blood ที่ออกมาจึงเป็นค่ามั่ว

ต่อมาเราจะมาเพิ่มความสามารถให้กับ class เรา ก็คือการใช้ Overloading method

Overloading method ดียังไง

Overloading method (หรือ Overloading function) ก็คือการสร้าง function ที่มีชื่อเหมือนกันหลายๆตัว แต่มี parameter ต่างกัน โดยการใช้งานก็ คือ เมื่อมีการเรียกใช้ชื่อ overloading function โปรแกรมก็จะดูว่า function ไหนที่มี parameter เหมาะสมที่สุดก็จะเข้าไปทำงานใน function นั้น มาลองดูตัวอย่างกันดีกว่าครับ

#include <iostream>
#include <string>

using namespace std;

class Player
{
    public:
        string name;
        void attack(Player p, int damage){
            p.blood_update(-5);
        }

        void blood_update(int b){
            blood += b;
            cout << "blood: " << blood << endl;
        }

        void blood_update(){
            cout << "blood not update" << endl;
        }

        Player(){
            blood = 100;
        }

        Player(string n){
            name = n;
        }

    private:
        int blood;
};

int main()
{
    Player cat;
    cat.blood_update(10);
    cat.blood_update();
    return 0;
}

ผลลัพธ์ที่ได้

blood: 110
blood not update

เราดู cat.bloodupdate(); ปกติถ้าเราไม่ใส่ parameter ที่เป็น int มันก็จะ error แต่ทีนี้เจ้า updateblood มันเป็น overloading function ที่ถ้าหากไม่มีการใส่ parameter จะเรียก update_blood() และแสดงข้อความว่า blood not update วันนี้ก็จบพื้นฐานเกี่ยวกับคลาสแล้วนะครับ




© 2019, Built with