ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • virtual 키워드
    정리필요2 2008. 6. 27. 20:53

    [네이버 지식인에서 퍼옴]


    virtual 이라는 키워드가 붙게되면...이 virtual 붙은 것은 실시간,,,즉,,,컴파일이 된 후의

     

    런타임에 바인딩되어 호출될 함수가 결정되죠~~

     

    정적, 동적 바인딩이 여기서 등장하죠...

     

    가상함수는 객체 타입의 포인터를 이용하여 호출할 때 의미가 있는 것이지,

     

    포인터 타입이 아닌 인스턴스로는 호출이 되지 않습니다...(중요 !!)

     

    보통,,,부모 클래스에서 가상함수를 선언했을 경우, 자식 클래스에서 이 함수를

     

    virtual 키워드 없이 오버라이딩 해도 되지만,,,이 함수는 가상함수이다~~ 이렇게

     

    명확히 알려주도록 하기위해, 자식 클래스에도 virtual 키워드를 붙여 주는것이

     

    좋습니다...

     

    class A{....

    virtual void fct(){cout<<"1";}

    };

    class B : public A{....

    virtual void fct(){cout<<"2";}  // 명확히 virtual 을 붙여주는 것이 좋다 !!

    };

     

    뭐 이렇게 하고 메인에서 A *a = new A; a->fct; 이렇게 하면 '2' 가 출력되는...

    (맞죠??? 갑자기 헷갈리네. A a 라고 선언하고  a.fct 해도 똑같이 2가 나올려나요???

    해봐야지)

     

    ==> A 타입의 포인터 a 는 A 타입의 객체를 생성하였으므로,,,A 타입 클래스의

     

           멤버만을 알고 있습니다...그러니,,,'2' 가 출력되는 것이 아니고 '1' 이

     

          출력되죠 !!

     

     

     

    class A{}

    class B : virtual  public A{}

    class C : virtual public A{}

    class D : public B, public C{}

     

     

    => 여기서 virtual 의 의미는??

     

         virtual 이 붙은 가상 기반 클래스는 잘 알다시피, "모호성" 을 피하기

     

        위함입니다...

       

         가상 기반 클래스가 아니라면...D 클래스가 생성시에 A 를 상속 받을 때,

     

         B에서 받을지 ??  C에서 받을지 모호하죠~~...컴파일러는 애매모호한 것을 아주

     

        싫어 합니다...

     

        그러므로,,,virtual 키워드로 인해, D 클래스에서는 B 와 C 클래스가 상속받은

     

        A 클래스를 하나로 인지하도록 하여, 모호성을 없애주고, D 는 오직 하나의

     

        A 클래스만을 인식합니다...

     

     

    *** 알아 두어야 할 점 ***

     

    보통, 상속의 경우에는 자식은 부모의 생성자 만을 호출할 수 있으나,

     

    가상 기반 클래스에서는 손자가 할아버지의 생성자를 호출한다는 점입니다...

     

    즉,  손자 -> 할아버지 생성자를 바로 호출할 수 있다는 것이죠...

     

    또한, 중간 단계의 클래스인 아버지 생성자(위에서는 B, C 레벨) 에서는

     

    A 의 생성자를 호출하지 않습니다..  A 는 B, C 의 것이 아닌 D 의 것이기

     

    때문입니다...

     

    예를 들어 봅니다..

     

     

    class A{
    protected :
     int a;
    public :
       A(int _a) : a(_a) { cout<<"A 생성"<<endl; }
     ~A( ) { cout<<"A 소멸"<<endl; }

    };

     

    class B : virtual public A{
    protected :
     int b;
    public :

        // A의 생성자 호출이 안됨

       B(int _a, int _b) : A(_a), b(_b) { cout<<"B 생성"<<endl; }
     ~B( ) { cout<<"B 소멸"<<endl; }

    };

     

    class C : virtual public A{
    protected :
     int c;
    public :

       // A의 생성자 호출이 안됨

       C(int _a, int _c) : A(_a), c(_c) { cout<<"C 생성"<<endl; }
     ~C( ) { cout<<"C 소멸"<<endl; }
        };

     

    class D : public B, public C{
     int d;
    public :

      // A의 생성자를 D에서 호출 !!...A 클래스의 멤버변수의 값은 B, C 클래스에서

      // 넘겨준 값은 무시되고, 직접 호출한 A 의 생성자 값만 인식한다 !!
     D(int _a, int _b, int _c, int _d) : A(_a + 100), B(_a + 1, _b), C(_a + 1, _c), d(_d) { }


     void Print( )
     {
      cout<<"a: "<<a<<endl;
      cout<<"b: "<<b<<endl;
      cout<<"c: "<<c<<endl;
      cout<<"d: "<<d<<endl;
     }
    };

     

    int main()
    {
     D ob(1, 2, 3 ,4);   // 인스턴스 생성 !!

     

     ob.Print();
    }

     

    위에서 보다시피,,,B 와 C 가 생성될 때는 별도로, A 의 생성자를 호출하지

     

    않음을 알 수 있습니다...

     

    D 에서 호출한 A의 생성자만 호출 됨을 알수 있죠~~

     

    원래는 부모의 생성자를 호출해야 하지만...

     

    A 생성

     

    A 생성

    B 생성

     

    A생성

    C 생성

    .....

     

    이런식으로 되어야 하는데 말이죠...이는 A 를 소유한 것은 B 와 C가 아닌

     

    D 클래스 라는 것을 의미합니다...좀 특이한 형태죠...

Designed by Tistory.