JAVA나 C++과 같은 객체지향언어를 공부하는데 첫 번째로 중요하다고 할 수 있는 개념은 클래스와 상속 입니다.

실제로 프로그램을 짜기에 앞서 클래스와 상속을 얼마나 효율적으로 잘 설계하느냐에 따라 앞으로의 개발난이도가 좌우된다고 해도 과언이 아닌데요.

이제 막 자바를 공부하기 시작한 초보자들 기준으로 클래스와 상속 개념에 익숙해졌다면 그 다음으로 공부해야 할 개념은 바로 다형성(polymorphism)입니다.

 

 


 

Q. 다형성이란

 

 

 

다형성이란, 쉽게 말해서 "조상클래스 타입의 참조변수로 자손클래스의 인스턴스를 참조할 수 있다"는 개념입니다.

이해를 돕기위해 '사람' 클래스를 만들어보았습니다.

 

class People{

    String name;

    int age;

   void working();  

   void sleeping();

}

 

 이 사람 클래스는 노동하고 잠자는 것말고는 딱히 정해진 것이 없습니다.(뭔가 슬프네요...) 

그래서 H백화점 VIP 고객으로 만들어주었습니다.

 

class HDepartmentStoreVip extends People{

    int purchasingAmount; //구매실적

    void purchasing();

}

 

(1) People p = new HDepartmentStoreVip(); 

-> 위에서 말한대로 조상클래스People의 참조변수 p자손클래스HDepartmentStoreVip의 인스턴스참조하는 것은 가능합니다. 

 

같은 타입의 클래스의 인스턴스를 참조하는 것도 물론 가능합니다.

(2) HDepartmentStoreVip h = new HDepartmentStoreVip(); 

 

하지만 당연히 차이가 존재하는데요, (2)와 같이 같은 타입의 클래스의 인스턴스를 참조할 때 참조변수는 모든 멤버를 사용할 수 있지만, (1)과 같은 경우는 애초에 People클래스에 존재하지 않는 purchasingAmount나 purchasing()과 같은 멤버는 사용할 수가 없습니다.

 

위의 개념을 이해했다면 자손클래스의 참조변수는 조상클래스의 인스턴스를 참조할 때는 어떻게 되는지 궁금할 것입니다. 정답은 "안된다" 입니다~! 애초에 자손클래스의 참조변수는 조상클래스의 멤버개수 이상이기 때문에 내가 참조하고자 하는 멤버가 없을 경우가 항상 존재합니다(그러지 않으면 굳이 만들 필요가...) .따라서 이런 경우는 프로그램 상에서 컴파일에러를 띄웁니다.

 

 


 

Q. 참조변수 형변환

 

 

기본변수와 마찬가지로 참조변수도 물론 형변환이 가능합니다. 상속관계에 있는 클래스 사이에서만 가능하고,

(1)자손->조상 (=upcasting이라고도 합니다.)

(2)조상->자손 (=downcasting)

위의 두 가지 케이스 모두 가능합니다.

 

(1)의 경우는 심지어는 조상의 조상의 조상... 까지도 형변환이 가능합니다. 하지만 여기서 두 케이스의 차이점은(1)의 경우에는 형변환이 생략가능하나, (2)의 조상에서 자손타입으로의 형변환은 생략이 불가하다는 점입니다. 간단하게 기본형 변수의 형변환만 떠올려봐도 큰 자료형에서 작은 자료형의 형변환은 생략이 불가했던 것처럼, 참조변수도 같은 원리로 적용된다고 보시면 될 것 같습니다.

 

위의 People과 HDepartmentVip 클래스로 예시를 들자면,

{

People p= null;

HDepartmentVip h1=null;

HDepartmentVip h2=new HDepartmentVip();

 

p=h2;  //->다음과 같은 경우에는 p=(People)h2; 에서 (People)형변환이 생략가능하지만,

h1=p;  //-> "error"!!!!

         //  이처럼 조상클래스 People에서 자손클래스 HDepartmentVip로 형변환할 때는

         //  무조건 h1=(HDepartmentVip)p; 과 같이 형변환을 명시해주어야 합니다.!!

}

 


오늘은 자바의 다형성개념과 참조변수의 형변환에 대해 정리하였습니다.

다음 포스팅에는 다형성의 세부개념에 대해 설명하겠습니다. 즐코하세요!

위 포스팅 내용은 윤성우의 열혈 C++ 책을 참고하였습니다.

 

C를 배우고 갓 C++을 입문하신 분들은 처음 C++소스코드를 접할 때

 

std::cout<< , std::cin>> 등의 입출력문과 <iostream> 헤더파일 말고도  다양한  새로운 문법들을 마주하게 되는데요

 

namespace도 그 중 하나입니다.

 

 

 

처음볼 때는 생소할 수 있지만, 몇 번만 반복해서 보다보면 금방 익숙해지는 개념입니다.

 

namespace란 이름 그대로 '공간에 이름을 붙여논다' 라고 이해하면 쉽습니다.

 

 


 

Q. 그렇다면 namespace는 왜 필요한 걸까요?

 

 

친구랑 만나기로 약속했다고 가정해봅시다. 

 

A:  토요일 두 시에 스타벅스에서 만나자~~

B:  어디 스타벅스?

A:  신촌 거기 있잖아?

B:  거기가 어디야?

 

위는 고구마 백개먹은 것 같은 대화입니다. 

 

A와 B가 어디 스타벅스인지 서로 정확하게 의사소통 전달이 안 되는 원인은 

 

1.신촌에 스타벅스가 여러개 있다.

2. "위 구역에 존재하는 유일한 스타벅스" 를 지칭하지 않았다.

 

위와 같은 이유 때문입니다. 

 

따라서 위 상황에서 A는 4번출구 방향 스타벅스 라고 스타벅스에 namespace를 부여해 주어야 합니다.

 

 

 

스타벅스에 4번출구와 8번출구라는 네임스페이스를 부여해 주었다.

 

 

namespace를 사용하는 방법은 위와 같습니다.

 

namespace 뒤에 원하는 이름을 붙여주고 괄호 안에 내용을 작성해주시면 됩니다.

 

예시를 보시면 Exit() 라는 똑같은 함수가 선언되었는데 에러가 나지 않는 모습을 확인할 수 있습니다.

 

그 이유는 다른 namespace 안에 소속되어 있기 때문입니다.

 

 

 

 

연산자 ::

 

 

어느 namespace안에 있는 함수인지 지칭할 때는 바로 연산자 :: 를 활용하여  

 

NAMESPACE명 :: 함수명( );

 

라고 명명해주면 됩니다.

 

 

 


Q. namespace 안에 namespace를 중복해도 써도 되나요?

 

생각해보면 4번출구와 8번출구에 있는 스타벅스는 한 둘이 아닐 것입니다. (합정에도 있고,, 홍대에도 있고..)

 

그렇기 때문에 우리는 정확한 위치를 명시하기 위해서는 더 많은 namespace가 필요한데요

 

 

 

 

 

 

따라서 저는 4번출구와 8번출구를 신촌이라는 namespace로 감싸주었습니다.

 

물론 신촌이라는 namespace는 서울, 서울이라는 namespace는 한국으로 더 많이 중복해서 감쌀 수 있겠죠?

 

내부의 변수나 함수에 접근하려면 아까와 같이 ::연산자를 사용하면 됩니다.

 

KOREA :: SEOUL :: SHINCHON :: EXIT8 :: Exit();

 

이것이 좀 길다면 이름공간에 대한 별칭을 지어줘도 됩니다.

 

namespace 신촌팔출=KOREA :: SEOUL :: SHINCHON :: EXIT8;

 

그러면 호출할 때 신촌팔출::Exit(); 로 축약을 할 수 있습니다.

 

 

사실 우리는 C++에서 입출력을 했다면 이전부터 namespace를 쓰고 있었을 것입니다.

 

std::cout , std::cin 에서 std가 바로 namespace이기 때문입니다.

 

헤더파일인 <iostream>에 선언된 std라는 namespace에서 우리가 그동안 입출력 함수를 불러와 쓰고 있었던 것입니다.

 

 

 


Q.근데 사실 맨날 std::를 붙이기 좀 귀찮은 것 같아요...

 

아마 많은 분들이 그간 std:: 를 붙이는데 많이 귀찮으셨을 거라 생각됩니다...(사실 저도..)

 

std namespace를 using이란 키워드를 이용하여 헤더 밑(전역부분) 에 선언을 하면

 

앞으로 일일히 std::를 붙이지 않아도 됩니다. 

 

 

 

 

 

 

하지만 만약 이것도 세줄이나 된다! 하시는 분들은 더 생략할 수도 있습니다.

 

 

 

위의 예시처럼 아예 std전체를 using으로 선언해버리면 됩니다.

 

아주 편해보이지만 , 첫 번째 예시보다는 이름이 충돌할 가능성이 높아지기 때문에 무조건 좋다고만 할 수는 없습니다.

 

 


오늘은 namespace에 대하여 알아봤습니다.

여기까지 읽어주셔서 감사합니다.

'Programming Language > C++' 카테고리의 다른 글

[C++이론] C++에서의 함수오버로딩  (0) 2020.07.17
[C++이론] C++에서의 입출력방식  (2) 2020.07.17
위 포스팅 내용은 윤성우의 열혈 C++ 책을 참고하였습니다.

 

 

C에서는 함수의 이름이 같다면 컴파일 오류가 발생합니다.

 

하지만 C++에서는 함수의 이름이 같더라도 컴파일 오류가 일어나지 않는데요

 

Q.왜 함수의 이름이 같은데 컴파일 오류가 나지 않을까요?

위 예시를 보면 void 형 함수 Naong 을 세 개나 선언했는데 컴파일 오류가 발생하지 않는 것을 확인할 수 있습니다.

 

C++에서 함수오버로딩이 허용되는 이유는 C++의 함수 호출방식 때문인데요.

 

C++에서는 함수를 호출할 때 (1)함수의 이름 과  (2)매개변수 로 구분하기 때문에

 

함수의 이름이 같더라도

 

1. 매개변수의 자료형이 다르다

2. 매개변수의 개수가 다르다

 

다음의 경우에 해당되면 다른 함수로 인식하는 덕분에 오버로딩이 가능합니다.


 

따라서

Melon 이라는 이름의 함수를 만들 때

 

void Melon(char n1){}

void Melon (int n1){}

void Melon(int n1, int n2){}

void Melon(char n1, char n2){}

 

위와 같이 만들어도 에러가 나지 않는 것을 확인할 수 있습니다.

 


 

하지만 주의해야 할 점은 

 

void Melon(char n1){}     int Melon(char n1){}

void Melon (int n1){}

void Melon(int n1, int n2){}

void Melon(char n1, char n2){}

 

 

다른 것은 다 동일한데 반환형을 다른 자료형으로 바꿨다고 해서 다른 함수로 인식되는 것이 아니라는 것입니다.

 

C++은 엄연히 두 가지 '함수의 이름'과 '매개변수' 로만 판단한다는 것을 다시 한 번 새겨봅시다~

'Programming Language > C++' 카테고리의 다른 글

[C++이론] namespace란 무엇일까?  (0) 2022.04.15
[C++이론] C++에서의 입출력방식  (2) 2020.07.17
위 포스팅 내용은 윤성우의 열혈 C++ 책을 참고하였습니다.

 

안녕하세요! (첫글이네요!)

 

유명한 기술블로거를 꿈꾸며 블로그를 시작하게 된 나옹입니다.

 

기록이라는 행위를 함으로써 거대한 지식의 흐름에 사막의 모래 한톨만큼이나마 일조해보겠습니다 ^^


 

C++은 C언어를 포함하고 있죠.

 

그래서 저희가 여태까지 C언어로 코드를 작성하면서  C++컴파일러로도 작성이 가능했습니다.

 

(여태까지 작성한 파일을 보면 .cpp일것이다)

 

 

하지만 C++은 C언어가 지니지 않는 문법적 특성도 아주 많이 가지고 있습니다.

 

우선 이번 글을 입출력문부터 살펴보고 가겠습니다.

 

 


 

Q.  C에서의 출력문은 printf인데 C++에서의 출력문은 무엇일까?

 

C언어로 작성한 코드

 

 

C++로 작성한 코드

 

위 두 코드의 출력된 결과는 

 

"나옹이는 금화를 갖고 있다."

"나옹이는 금화를 1개 갖고 있다."  로 동일하다는 것을 알 수 있습니다.

 

더불어 출력을 할 때 C++에서 C언어와 다른 세 가지 다른 문법적 특징을 발견할 수 있습니다.

 

첫 번째로는

1. 헤더파일 선언문입니다.  

 

 

C에서는 입출력을 할 때

 

printf와 scanf호출의 목적으로  #include<stdio.h>를 써줘야 한 반면,

 

C++에서는 입출력을 할 때  #include <iostream>을 선언해야합니다.

 

(여기서 왜 c++에는 뒤에 .h가 붙지 않나 하는 의문이 들 수 있는데요,  과거에는 뒤에 .h를 붙였는데 현재 표준 헤더파일 선언에서는 확장자를 붙이지 않고 있다고 합니다.)

 

 

 

두 번째 특징으로는 

2. std:cout  와  <<  에 의한 출력입니다.

 

 

사실상 출력을 위한 기본적인 도구는 std:cout << "내가 말하고 싶은 문장"  입니다

 

여기서 뒤에 덧붙이고 싶은 문장이 있다면 << "덧붙이고 싶은 문장" 을 추가해주면 되는 것입니다.

 

그리고 편리한 점은 C언어와 달리 %d와 같은 서식문자를 쓸 필요없이 바로 변수(gold)를 사용할 수 있다는 점입니다!!

 

 

마지막 특징으로는

 

3. 개행입니다.

 

해당 콘솔 화면은 위 코드를 출력한 결과물인데요

 

자동적으로 개행이 된 것을 확인할 수 있습니다.

 

무엇으로 인해 개행이 된 걸까요?

 

바로 << 다음에 오는 

 

std::endl;  으로 인해 다음 문장으로 넘어간 것입니다.

 

 

이로써 출력문에 대한 세 가지 특징 설명을 마쳤습니다.

 

 


Q.  그럼 scanf대신에 C++에서는 무엇을 쓸까?

 

일단 입력을 할 때도 마찬가지로 헤더파일은 #include<iostream>을 선언해주셔야 합니다.

 

출력문과 다른점은 입력문에는 std::cout대신에 

 

 

std:cin   와 >>연산자가  사용된다는 점입니다.

 

여기서 추가로 설명드릴 점은 

 

std:cin >> 첫 번 째 변수 >> 두 번 째 변수;

 

위와 같은 경우에는 순서대로 입력이 인식된다는 점입니다.

 

8행에서   std::cin >> 나옹이>> 피카츄; 라고 작성을 했는데요

 

 

 

콘솔을 돌리면 역시 입력한 순서대로 나옹이와 피카츄 마리수가 나오는 것을 확인할 수 있습니다.

 


 

 

입출력에 대한 설명은 여기까지 입니다. 다들 즐거운 하루 되세요~~

'Programming Language > C++' 카테고리의 다른 글

[C++이론] namespace란 무엇일까?  (0) 2022.04.15
[C++이론] C++에서의 함수오버로딩  (0) 2020.07.17

+ Recent posts