Programming Lecture 11-1. C++ Namespace ~ Derived Class
2018년 2월 8일
이번주 목요일에 나는 마이크로소프트 한국지사로 TIPS 11차시 수업을 들으러 갔습니다. 강사는 Tipssoft의 대표이사 김성엽 이사님 이십니다. 대표님은 마이크로소프트 C++프로그래밍 부문 MVP로 활동 하고 계십니다.
이번 수업에서는 C++ namespace부터 다형성까지 배웠습니다.
Namespame
프로그래밍은 앞으로 혼자보다는 팀 작업이 많을 것입니다. 그렇게 되면 개개인이 만든 함수의 이름이 겹칠 수가 있겠죠. 그래서 C언어에서는 같은 이름의 함수를 구별하기 위해 아이덴티티코드를 앞에 삽입 후 언더 바(_)를 삽입하는 작업을 합니다. 하지만 C++에서는 규모가 큰 프로젝트를 진행 하기 위해 만들어진 언어이기 때문에 팀 작업을 하게 되면 함수의 이름이 겹칠 수 있는 불상사를 해결하려 노력 했습니다. 그 결과 컴파일러에서 namespace라는 독립적인 공간을 제공하게 되었습니다. namescope라는 공간을 사용하기 위해서 scope라는 연산자가 도입되었습니다. scope연산자는 ::키워드를 사용하며 대상의 종속 관계를 표현 할 수 있습니다. Using namespace는 namespace의 scope문법을 항상 적어야 한다는 불편함의 대안입니다. 특정 namespace의 함수를 많이 사용한다면 using namespace (이름);으로 선언하여 scope를 생략하고 사용할 수 있습니다. 아래는 namespace를 사용하는 예시입니다.
scope연산자에 대한 응용
scope연산자는 namespace에만 사용될 수 있는 것은 아닙니다. class에도 사용할 수 있습니다. 이런 경우는 자주 없지만 예를 들어 특정 클래스의 멤버함수와 전역함수의 이름이 같을 경우 scope를 통해 멤버함수 안에서 전역함수를 호출 할 수 있습니다. scope앞에 클래스등 아무것도 적지 않을 경우 이는 전역으로(어디에도 소속되어있지 않은) 해석합니다. 즉, 전역변수로 dat변수가 선언되어있고, main문 안에 dat변수가 선언되어있을 경우 dat은 main문 안의 dat을 의미하고 ::dat은 전역으로 선언된 dat변수를 의미합니다. 다음은 class와 scope의 응용입니다. 이는 header파일과 함수 구현파일을 분리하는 방법입니다. 클래스를 헤더파일에 모두 선언만 해놓고, 다른 소스파일에 멤버함수를 scope를 통해서 구현합니다. 장점은 클래스 선언부가 짧아지게되고, 다른사람에게 주요소스파일을 유출 되지 않는다는 점입니다. 이해가 되시지 않는다면 김성엽 대표님의 블로그로 링크하겠습니다.
https://blog.naver.com/tipsware/221056673054
- 클래스를 서로 사용해야하는 경우가 있습니다. 재귀가 아니고 상호 호출 방식으로 이름 지으면 좋을 것 같습니다. Class A,B가 있다고 할 때(순서는 A, B순서),
- 소스파일 최상단에 class B;로 컴파일러에게 아래 B클래스가 있음을 알려줍니다.
- class A를 정의할 때 B형 포인터형으로 멤버변수를 선언합니다.
- class B를 정의할 때는 A형 변수를 멤버변수로 선언합니다.
- 하단에 A::를 이용하여 객체생성자를 만들고 내부에 new연산자로 B클래스 메모리를 할당합니다.
이 또한 코드로 구현하기에 저의 설명이 부족하기 때문에 김성엽 대표님의 블로그로 링크하겠습니다.
https://blog.naver.com/tipsware/221067455721
new, delete
동적 메모리 할당에 대한 단원입니다. C언어에서는 malloc, calloc등의 함수로 구현하였지만, C++언어에서는 Heap영역에 대한 중요성을 인지하게 되어 연산자로 우선순위가 상승되어져 사용됩니다. C언어에서는 동적할당이 함수였기 때문에 컴파일러에게 내가 ‘어떤공간으로 사용하겠다’를 형 변환(casting)을 이용해서 하였었습니다. 하지만 C++언어에서는 연산자가 되었기 때문에 내가 어떤 공간으로 얼마만큼 사용 할 것인지를 일일이 설명하지 않고, 선언과 동시에 할당이 되어집니다. 예를 들어, 4바이트 Heap공간을 확보하기 위해서
C언어에서는 int p = (int)malloc(sizeof(int)); 와 같이 할당하였지만,
C++언어에서는 int *p= new int;로 간결하게 할당이 가능합니다.
New 연산자의 사용법은 ‘포인터’=new’할당하고 싶은 크기의 자료형’; 로 바뀌었습니다. 배열과 같이 큰 공간의 메모리 할당은 Int *p= new int[10];로 간단하게 표현이 가능 해졌습니다.
다음은 delete연산자 입니다. 이것은 C언어의 free함수와 같은 역할을 하지만 차이점은 free함수에서는 객체파괴자가 작동을 하지 않지만 delete연산자에서는 작동 하게 됩니다. 이 것은 new연산자에서도 마찬가지로 malloc함수를 통해서 메모리 할당을 하여도 되지만, new를 사용해야 객체가 생성 된다는 문제점이 있습니다. 이것이 C++언어에서 new와 delete연산자가 추가된 이유입니다.
delete연산자는 사용법이 간단합니다.
Int *p= new int; delete p;
Int *p=new int[10]; delete[] p;
이렇게 사용해야 합니다. 배열메모리를 확장 했을 때, delete뒤에 []는 반드시 적어 주어야 합니다.This 포인터
C++언어에서 class를 생성하고 main함수에서 사용을 해보면 포인터가 다 사라졌음을 느낄 수 있습니다. C언어에서는 멤버함수대신 포인터를 인자로 받는 함수를 만들어서 포인터를 이용해서 값을 변화시켰지만 C++언어에서는 그저 멤버함수에 인자를 넣어주는 것으로 값 변화가 가능했습니다. 이 것은 프로그래머에게 포인터를 보이지 않도록 숨겼기 때문에 가능한 일입니다. 그리고 그 가운데에 this라는 이름의 포인터가 가장 큰 역할을 했습니다. this포인터는 멤버함수가 선언된 클래스의 포인터형태를 const로 가지고 있습니다. 즉, 사용자가 함부로 바꾸지 못하도록 선언되어져 있음을 뜻합니다. 실제 코드에도 보이지 않습니다. 하지만, 숨겨져 있어 사용은 가능합니다. 그래서 멤버함수 내부에는 this라는 이름의 포인터를 선언 불가합니다.
그런데 이 this포인터를 사용해야 하는 경우가 있습니다. 멤버함수 내부의 지역변수와 멤버변수의 이름이 같은 경우입니다. 이 경우엔 컴파일러가 그 변수이름을 사용할 때 지역변수인지, 멤버변수인지 모르기 때문에 꼭 this->를 사용하여 멤버변수를 가리켜야 합니다. 아니면 컴파일에서 오류가 발생합니다. this포인터의 다른 용도는 ‘멤버함수에서 멤버함수를 호출한 객체의 주소를 다른 함수로 전달할 필요가 있을 때, 외부에서 객체의 주소를 전달받아서 사용할 필요 없이 this 포인터를 활용 하면 됩니다. ‘ 말이 조금 어려웠습니다. 아래 링크를 보시면 조금 더 자세히 알 수 있을 것입니다. (위와같이 김성엽 대표님 블로그입니다.)
https://blog.naver.com/tipsware/221068047046Default Arguments(기본 인자)
이번 Topic의 개념은 매우 간단합니다. 기본인자 라는 뜻으로, 사용자가 특정 값을 지정하지않을 경우 프로그래머가 지정 해놓은 값을 인자로 삼고 함수를 사용한다는 개념입니다. 아래에 기본인자에 대한 예시입니다.
위와 같이 마지막 인자에 값을 대입하지 않았습니다. C언어라면 오류가 났겠지만, 오류가 나지않고, 정상적으로 컴파일이 되었습니다. Default Arguments개념 덕분입니다. Default Arguments는 사용 조건이 있습니다. 오른쪽부터 인자를 설정 할 수 있습니다. 혹시나 오른쪽은 기본인자를 설정 하지 않고 왼쪽이나 가운데가 기본인자를 설정 하였다면 오류가 발생합니다. 또한 함수의 proto-type을 정립했다면 proto-type혹은 정의부분 둘 중 한 곳에서만 기본인자를 설정 할 수 있습니다.Derived Classes(파생 클래스)
C++언어의 꽃에 다다랐습니다. 이번 Topic은 파생 클래스 입니다. 파생클래스가 나타나게 된 배경은 유지보수에 있습니다. 만약 한가지 함수만 다르고 전부 다 똑 같은 클래스 A, B가 있다고 합시다. B를 사용하기 위해서는 A의 코드를 copy & paste후에 변화시킬 함수만 변경하면 됩니다. 하지만 A의 원래코드 중 다른 함수에서 문제가 생겼습니다. 그렇다면 그 기능을 해결하기 위해서는 A, B클래스 모두를 고쳐야 한다는 번거로움이 있습니다. 지금은 예시가 2개여서 그렇지 만약 비슷한 클래스가 10개, 20개가 있다면 상당히 귀찮고, 번거로운 작업이 될 것입니다. 그만큼 작업의 효율도 떨어지게 되는 것이죠. 이러한 이유 때문에 파생클래스라는 개념을 C++는 사용합니다.
- 위와 같은 5/3은 1이라는 결과가 나왔죠. 그래서 저는 몫이 아닌 나눈값을 구하기 위해 위에 sy_calculator 클래스를 보수해야 합니다. 기존의 몫을 구하는 기능을 가진 클래스는 그대로 두고 새 클래스를 만드려 합니다. 파생클래스라는 개념을 통해 copy & paste를 사용하지 않고, sy_calculator의 내용을 바꿀 것 입니다.
- 아래와 같이 새로운 파생클래스 sy_calcualtor_2를 만들었습니다. 이 클래스에서는 divide함수가 몫이 아닌 나눈값을 제대로 구해주네요. Sy_calculator_2에 사용된 divide함수는 sy_calculator에 사용된 divide함수에 오버라이딩 이라는 기능을 활용한 경우입니다. sy_calculator_2는 sy_calculator에게 상속을 받았다 표현하고 그 등급은 public등급으로 상속 받았다는 것을 의미합니다. public등급으로 상속을 시키고 멤버함수에 대해 overriding기능을 사용하면 똑 같은 이름의 함수기능을 바꿀 수 있습니다. 위에 사진과 마찬가지로요. 또한 자식함수에서 오버라이딩을 통해 함수를 재정의 하는 경우 namespace를 통하여 부모클래스의 함수를 호출 할 수 있습니다. 상속이 같이쓴다는 의미가 아닌 복사 & 붙여넣기를 한 코드가 생략되어있다고 보면 이해하기 쉬울 것 입니다.
우리는 위와 같은 경우 한 줄의 코드에서 문제가 생겼을 때 두군데를 고쳐야 된다 했습니다. 하지만 파생클래스 개념을 사용하면 한번만의 고생을 하면 됩니다. 아래에 예시를 보시겠습니다.
분명 sy_calculator 클래스에서만 minus함수를 고쳤지만 sy_calculator_2 클래스에서의 minus함수까지 고쳐진 모습입니다. 순서를 바꿈으로써 두 클래스 모두 다 minus함수가 올바르게 고쳐졌음을 확인 할 수 있습니다. 이처럼 파생클래스를 이용하면 유지보수가 매우 편해지기 때문에 많이 사용하게 됩니다.
환영합니다~팔로우 하겠습니다 ^^ 스팀잇 가입과 알아 두셔야 할점들 간단하게^^
일단 1.팔로우먼저50-100명한다2.그리고 글을쓴다(이전에 글 써봐야 잘 노출이 안된다)3.보팅은하루에10~15 회정도만보팅 80%유지 4.다른사람 보팅 할때는 30분이상 지난 글에 보팅을 한다( 바로하면 보팅수익없음)5.제목 오른쪽에 온천 표시 안 나오도록, 1스팀이 1USD 이상일 때 보상은 50:50으로 설정6.댓글소통을 많이하라~!! 스팀잇을누벼라~!! ***보팅과 소통은 사랑입니다. 그러나 뉴비는 보팅이 약합니다 보팅 안하는게 아니라 못해주는 경우가 더더 많습니다 ㅠㅠ 보팅 채우는 시간 때문입니다. 열심히 부지런히 스파업 하세요!!
Congratulations @pentalvega! You received a personal award!
Click here to view your Board of Honor
Congratulations @pentalvega! You received a personal award!
You can view your badges on your Steem Board and compare to others on the Steem Ranking
Vote for @Steemitboard as a witness to get one more award and increased upvotes!