개발/JAVA

C++ 의 virtual 함수. 가상화. JAVA랑 C++의 차이점

신매력 2013. 7. 26. 00:01

가상화에 대해서 검색해보다가 사소하게 생각하며 지나친 부분에대해 새로이 알게됐다.

C++에 있는 virtual 키워드의 용도, 

그리고 JAVA와의 차이점을 알게 되었다.



1. C++에서의 상속


class Parent {
    public :
        Parent(){};
        ~Parent() {};

    

        void foo() {
            std::cout << "parent!!!";
        };
};

class Child : public Parent {
    public :
        Child(){};

        ~Child() {};

    

        void foo() {
            std::cout << "child!!!";
        };
};

int main(){
    Parent* p = new Child();
    (p)->foo();

    

    return 0;

}

 


결과 >>


 parent!!!



Parent* p = new Child();


이 것을 통해 불려진 foo함수에서, child의 foo가 아닌 parent의 foo가 호출되는 것을 볼 수 있다.

이유는, 컴파일러가 포인터의 타입을 보고 타입에 맞는 메소드를 찾아주기 때문이다.



그러나, 부모의 foo 메소드 앞에 virtual 이라는 키워드를 붙인다면???

부모가 아닌 child의 foo 메소드가 호출된다.


즉, 생성된 객체에 대한(자식) 메소드가 호출된다는 것이다.


상속이 되고 나서 오버라이드 된 객체에 대해 사용해야 할 때 virtual 키워드를 사용하면 된다.



2. Java에서의 상속


Parent

public class Parent {

public void foo() {

System.out.println("parent!!!");

}

}


Child

public class Child extends Parent {

public void foo() {

System.out.println("child!!!");

}

}


Test

public class Test {

public static void main(String[] args) {

Parent p = new Child();

p.foo();

}

}



결과 >>


 child!!!



Java의 경우 선언된 타입에 상관 없이 생성된 객체(자식)의 함수를 바로 호출한다.


Java에서는 너무도 당연하게 이렇게 사용해왔는데, C++에선 안그렇다는 사실에 새삼 놀랐다 ㅋㅋ


-------------------------------------------------------------------------------------------



자, 그렇다면 아래의 경우에는 어떻게 될까?





Animal 데이터타입으로 보이지만, 자바에서는 new를 하는 객체가 저장되는 것이라고 했다.


그럼 Dog로 생성되었을텐데, Cat으로 캐스팅 된다면?

런타임 익셉션이 발생한다.



Java에서는 겉만 Animal일 뿐, new로 만들어진 그 객체라는 사실을 잊어서는 안된다 ㅋㅋ







그럼 C++에서는 저렇게 하면 어떻게 될까?


Animal* animal = new Dog();


처음 생성시는 위에 설명했듯 포인터 타입인 Animal의 noise()가 호출될 것이다.

Cat으로 캐스팅하면 문제 없이 Cat으로 캐스팅 된다.



그럼 자바처럼 virtual 키워드를 붙이게 되면?


익셉션 발생 없이 Dog의 메소드인 bark가 출력된다.(캐스팅 되지 않은채로 그냥 그 객체 호출)




이거 참 오묘하네 ㅋㅋㅋㅋ