Java와 C++은 문법적으로 상당히 유사합니다.
java를 설계할 때 C++ 개발자들이 쉽게 배울 수 있도록 만들었기 때문입니다.
하지만 차이점도 여러 개가 있습니다.
설계 목표
Java는 보안, 이식성, 빠른 개발에 비중을 두었고
C++은 속도와 C언어의 하위 호환성을 중점으로 두었습니다.
C++은 절차지향언어인 C의 효율성을 개선하기 위해 OOP(Object Oriented Programing)을 결합한 것이기 때문에 완벽한 OOP가 아닌 절차지향도 섞여 있습니다.
클래스
Java는 기본 단위가 Class로 거의 완전한 OOP라 볼 수 있습니다.
C++은 C언어의 상위 호환이기 때문에 절차지향이 섞여있습니다.
컴파일과 런타임의 차이
Java는 가상 머신 바이트 코드로 컴파일하며 실행시키려면 가상머신(JVM)이 필요합니다.
C++은 각 OS(운영체제 Window, Linux, Mac )의 머신에 맞는 기계어로 컴파일합니다.
이 때문에 C++은 Java보다 빠릅니다.
JVM(Java Virtual Machine)
자바를 실행하기 위한 가상 기계
자바는 OS에 종속적이지 않는다. 종속받지 않고 실행하기 위해선 JVM이 OS위에서 Java를 실행시킵니다.
보안성
JAVA가 보안성이 더 높습니다. (JVM이 메모리를 관리하기 때문에 해커가 메모리를 조작하기 어렵습니다. C++은 프로그래머가 메모리를 관리하기 때문에 쉽습니다.)
또한 Java는 몇 가지 보안 메커니즘을 구현하여 잘못된 프로그램으로 인해 생기는 피해를 막아주도록 설계되어 있습니다.
바인딩
Java의 바인딩 : 동적 바인딩
- 런타임에 기반하여 Method를 호출
- 별도의 데이터 관리가 필요하고, 불필요한 오버헤드가 붙을 수 있습니다.
C++ : 정적 바인딩
- 컴파일 타임에 함수 호출을 결정, 프로그램 실행 중 불필요한 오버헤드가 없습니다.
- 부모 클래스의 함수를 오버라이딩 하는 과정에서 정적 바인딩으로 인한 문제가 발생하기 때문에 virtual 키워드를 제공한다(가상 메소드)
바인딩
일반 함수를 정적 바인딩, 가상 함수를 동적 바인딩이라고 생각하면 됩니다.
정적 바인딩 : 컴파일 시, 어떤 함수를 호출할지 결정
(장점) 다형성(polymorphism)으로 인해 융통성을 갖게 됩니다.
(단점) 실행속도가 미세하지만 느립니다.
동적바인딩 : 런타임 중, 실행코드가 결정
(장점) 실행속도가 동적바인딩보다 빠릅니다.
(단점) 융통성이 적습니다.
문법의 차이
C++은 C의 상위호환으로서, 프로그래머에 의한 메모리 관리제어, Pointer(포인터), Pre-Processor(전처리기) 등의 기능을 전부 유지합니다.
Java는 위의 기능들과 버그를 일으킬 수 있는 기능을 전부 제거
C++에서는 동적으로 할당된 메모리는 직접 해체해야 하지만, Java는 가비지 컬렉터(Garbage Collector)가 자동으로 해제해줍니다.
C++의 기능인 연산자 오버로딩, 다중 상속을 사용할 수 없습니다.
대신에 interface를 사용해 다중 상속을 흉내낼 수 있습니다.
- Java에서 모든 객체가 reference로 전달되지만, C++에선 기본적으로 객체를 값으로 전달한다.(객체는 Array[], Class들을 말하며, int, long, double과 같은 primitive type은 값으로 전달된다.)
- Java에서 C++에서처럼 자동 casting(=cascading)을 하지 않지만, 최근 버전에서 제네렉이나 오토박싱 같은 기능이 추가되어 여러 상황에서 자동 casting이 가능합니다.
- Java에서는 모든 메소드가 가상메소드이다. 즉, 래퍼런스 유형이 아니라 객체 유형에 따라 메소드 구현이 결정된다. C++에서는 가상 메소드를 별도로 선언해줘야 한다.
- Java에서는 원시 데이터형의 크기가 정의되어 있지만, C++에서는 구현에 따라 데이터 형의 크기가 달라진다.
기본에 만든 C코드가 있고, 성능이 매우 중요할 때는 C++를 쓰는 쪽이 유리하지만, 이식성, 보안, 개발 속도 등이 중요한 상황에서는 Java와 C#을 선택하는 것 이다.
상속
Java가 C++보다 단순한 상속 체계를 지원합니다.
첫째, C++ 다중 상속을 지원하고 Java는 그렇지 않습니다.
다중 상속이란 하나의 클래스가 두 개 이상의 클래스를 상속하는 것을 말합니다.
다중상속을 지원하는 언어에서는 다이아몬드 문제가 발생하는데 C++은 다이아몬드 문제를 회피할 수 있는 기능을 제공합니다.
둘째, C++은 friend 키워드를 지원하고 Java는 그렇지 않습니다.
특정 class에 friend키워드를 붙여서 클래스 혹은 함수를 선언하면 명명된 클래스와 함수는 그 class의 private, protected area에 접근할 수 있습니다. 하지만 이 방법은 객체의 은닉성을 파괴하므로 특수한 경우가 아니면 사용하지 않기를 권장합니다.
셋째, Java는 Interface를 지원하고 C++은 그렇지 않습니다.
다중상속이 지원되지 않는 Java는 Interface를 통해 다중상속을 어느 정도 흉내낼수 있습니다. Java에서는 하나의 Class가 여러 개의 Interface를 Implement 할 수 있습니다. Interface는 상수와 추상메소드로만 구성되어 있으므로 여러 개의 Interface를 implement 하더라도, 다이아몬드 문제를 발생시키지 않습니다.
다이아몬드 문제란?
메모리 처리
Java와 C++은 메모리 처리에도 차이가 있습니다.
첫째, Java는 객체를 메모리의 Heap 영역에만 할당할 수 있으나, C++은 Heap과 Stack 영역 모두에 할당 가능합니다.
C++에서 new 키워드를 통해 객체를 생성하면 Heap 영역에 객체가 할당되고, 일반적인 변수 선언 방식을 택하면 Stack 영역에 할당됩니다. Java는 일반적인 변수 선언 방식으로 객체를 생성할 수 없습니다.
둘째, Java는 메모리 해제가 자동으로 이루어지지만, C++은 프로그래머가 수동으로 해야합니다.
Java에서는 Garbage Collector가 미사용 객체 등의 자원을 자동으로 해제하며, 프로그래머는 수동으로 GC(가비지 컬렉터)를 조작할 수 없습니다. 반면 C++은 Destructor(소멸자)를 통해 메모리 해제가 가능합니다.
문법 및 기능
언어의 성격과 문법적 차이가 있습니다.
첫째, C++에서는 연산자오버로딩을 지원하지만, Java는 그렇지 않습니다.
연산자 오버로딩은 단어 그대로 연산자를 재정의하여 활용하는 것인데, 객체간 연산에 활용할 수 있습니다.(예를 들면, * 연산을 재정의하여 객체와 객체를 * 연산처리 할 수 있습니다.) Java는 만들어질 때부터 연산자 오버로딩을 지원하지 않는 방향으로 개발되었습니다.
들째, Java는 익명클래스(Anonymous Class)를 지원하지만, C++은 그렇지 않습니다.
익명클래스는 Java에서 지원하는 기능인데, 말 그대로 이름이 없는 클래스입니다. 인터페이스 메소드 중 하나만 재정의하고 싶을 때 자주 사용되며, 클래스의 선언과 객체의 생성이 동시에 이루어지는 형태를 띄고 있습니다. Java는 익명클래스를 통해 함수형 프로그래밍의 형태를 어느 정도 흉내낼수 있습니다.
정리
C : 순차지향 언어
C++ : 객체지향 언어, 동적 메모리 직접 관리
Java : 객체지향 언어, 동적 메모리 갈바지 컬렉션이 관리
Java
객체지향언어 입니다.
보안, 이식성 빠른 개발에 용이합니다.
컴파일 하려면 가상머신, JVM 필요합니다.
가비지 컬렉터가 자동으로 메모리를 정리해줍니다. (보안에 강합니다)
다중 상속이 불가능하지만 Interface를 통해 비슷하게 흉내낼 수 있습니다.
C++
C와 호환을 위해서 절차지향도 섞인 객체지향언어 입니다.
속도가 빠르고, C언어와 하위 호환성을 염두해 설계되었습니다.
각 OS에 맞는 기계어로 컴파일 합니다. 이 때문에 자바보다 속도가 빠릅니다.
프로그래머가 수동으로 메모리를 정리합니다. (보안에 취약합니다)
다중 상속을 지원합니다.
참조
https://theheydaze.tistory.com/598
https://showmiso.tistory.com/252