Inheritance

9.1. การสืบทอด Inheritance

Inheritance คือการใช้ attributes และ method ของ Base class ซึ่งสามารถทำได้โดยเติมชื่อ Base class ไปหลังเครื่องหมาย ":" เช่น

class Derived: public Base{
    ...
};

โดยการกำหนดการเข้าถึงเป็น public จะทำให้การเข้าถึงใน base class ยังคงเหมือนเดิม

9.2. การเข้าถึง Access

  • public: ทุกคนเข้าถึงได้
  • private: เฉพาะ meber functions ในคลาสตัวเอง
  • protected: เฉพาะ meber functions ในคลาสตัวเองและคลาสที่สืบทอด
Access public protected private
Same class yes yes yes
Derived classes yes yes no
Outside classes yes no no
        class Base { 
            private: 
                int MyPrivateInt=1; 
            protected: 
                int MyProtectedInt=2; 
            public: 
                int MyPublicInt=3; 
        }; 
        class Derived : public Base { 
            public: 
                int foo1() { return MyPrivateInt;} // Won't compile! 
                int foo2() { return MyProtectedInt;} // OK 
                int foo3() { return MyPublicInt;} // OK 
        }; 
        class Unrelated { 
        private: 
            Base B; 
        public: 
            int foo1() { return B.MyPrivateInt;} // Won't compile! 
            int foo2() { return B.MyProtectedInt;} // Won't compile 
            int foo3() { return B.MyPublicInt;} // OK 
        };

output

derived.foo2(): 2
derived.foo3(): 3
unrelated.foo3(): 3

9.3. private, public, and protected inheritance

        class A{
            public:
                int x;
            protected:
                int y;
            private:
                int z;
        };

        class B : public A {
            // x is public
            // y is protected
            // z is not accessible from B
        };

        class C : protected A {
            // x is protected
            // y is protected
            // z is not accessible from C
        };
        // 'private' is default for classes
        class D : private A {
            // x is private
            // y is private
            // z is not accessible from D
        };

9.4. ตัวอย่างการเปลี่ยนการเข้าถึงด้วยการสืบทอด

ฟังก์ชัน getArea() ไม่สามารถเข้าถึงจาก main() เพราะการเข้าถึงถูกเปลี่ยนเป็น protectec ด้วยการสืบทอด

        class Rect{
            public:
                int width,height;
                Rect(){}
                int getArea(){ return width*height; }
            protected:
                int key;
        };
        class Square: protected Rect{
            public:
                Square(int edge){
                    width=edge;
                    height=edge;
                    cout<<key<<endl; //ok
                    cout<<width<<endl; //ok
                }
        };
        int main(){
            Square mysq(5);
            //cout<<"mysq.area() is "<<mysq.getArea()<<endl; //cannot access getArea()
            return 0;
        }

9.4.1 private inheritance with scope (avoid using this confused pattern)

ถ้าไม่ใช้ scope "A::", B จะไม่สามารถเข้าถึง print() เพราะสืบทอดแบบ private เราไม่ควรใช้ pattern นี้ในการเขียนโปรแกรมเพราะอาจเกิดความสับสนเรื่องการเข้าถึง

        #include<iostream>
        using namespace std;
        class A{
        public:
            void print(){cout<<"it's A"<<endl;}
        };
        class B:private A{
        public:
            void print(){
                cout<<"it's B"<<endl;
                A::print();
            }
        };
        class C: private B{
        public:
            void print(){
                cout<<"it's C"<<endl;
                B::print();
            }
        };
        int main(){
            C c;
            c.print();
            return 0;
        }

output

    Running /home/ubuntu/workspace/code941_private_inheritance.cpp
    it's C
    it's B
    it's A

9.4.2 protected inheritance

ถ้าต้องการป้องกันการเข้าถึงจากนอกคลาส protected inheritance จะเข้าใจได้ง่ายมากกว่า private inheritance

        #include<iostream>
        using namespace std;
        class A{
        public:
            void print1(){cout<<"it's A"<<endl;}
        };
        class B:protected A{
        public:
            void print2(){
                cout<<"it's B"<<endl;
                print1();
            }
        };
        class C: public B{
        public:
            void print3(){
                cout<<"it's C"<<endl;
                //if class B: private, C cannot access print1() (with in class C)
                //if class B: protected, C can access print1()  (with in 
                print2();
            }
        };
        int main(){
            C c;
            c.print3();
            return 0;
        }

output

        Running /home/ubuntu/workspace/code941_private_inheritance.cpp      
        it's C 
        it's B  
        it's A

9.5. Order of constructing and destructing

ถ้ามีการสืบถอดหลายชั้น ลำดับการสร้างและการทำลายจะเป็นอย่างไร

    #include<iostream>
    using namespace std;
    class A{
    public:
        A(){
            cout<<"Constructing A"<<endl;
        }
        ~A(){
            cout<<"Destructing A"<<endl;
        }
    };
    class B:private A{
    public:
        B(){
            cout<<"Constructing B"<<endl;
        }
        ~B(){
            cout<<"Destructing B"<<endl;
        }
    };
    class C: private B{
    public:
        C(){
            cout<<"Constructing C"<<endl;
        }
        ~C(){
            cout<<"Destructing C"<<endl;
        }
    };
    int main(){
        C c;
        return 0;
    }

output

Running /home/ubuntu/workspace/code950_sequenceConDeCon.cpp
Constructing A
Constructing B
Constructing C                                                                                         
Destructing C
Destructing B                                                                                          
Destructing A

9.5.1 order of constraction and deconstruction

สังเกตผลลัพธ์ในการสร้างและทำลาย a1 และ a2 โดยการสร้างเป็นไปตามลำดับซ้ายไปขวา ส่วนการทำลายจะเริ่มทำลายตัวที่ถูกสร้างหลังสุดก่อน

        #include<iostream>
        using namespace std;
        class A{
        public:
            int id;
            A(int _id=0){
                id=_id;
                cout<<"Constructing A "<<id<<endl;
            }
            ~A(){cout<<"Destructing A "<<id<<endl;}
        };
        class B:public A{
        public:
            A a1,a2;
            B():a1(1),a2(2){cout<<"Constructing B"<<endl;}
            ~B(){cout<<"Destructing B"<<endl;}
        };
        class C:public B{
        public:
            C(){cout<<"Constructing C"<<endl;}
            ~C(){cout<<"Destructing C"<<endl;}
        };
        int main(){
            C c;
            return 0;
        }

output

Running /home/ubuntu/workspace/code950_sequenceConDeCon.cpp
Constructing A 0
Constructing A 1
Constructing A 2
Constructing B
Constructing C
Destructing C
Destructing B
Destructing A 2 
Destructing A 1
Destructing A 0

results matching ""

    No results matching ""