삽질의 현장/- C++

#020_시(c)시(c)해서 C++?!_ 되돌아보자 씨쁠쁠 ...

shovelman 2015. 7. 18. 02:16

안녕하십니까~ 삽잡이입니다...


막장... 삽잡이 푸하하...

내가 이해한 바탕으로 쉽고 재미있게 블로그에 풀어쓰자는 취지는

이미 안드로메다로 떠났습니다...

아닙니다... 회생할 수... 있을까요... 있겠지요... 흐헉헉


아무튼... 지금까지 제가 C++ 에 대한 글을 올리며 

어느정도 C++에 대한 문법적인 요소들은 한번씩 밟아온것 같아서... (밟아...?)

다시한번 곱씹어보는 시간을 가져보려 합니다...


참고로 이번 글은... 뭐 이전글들도 다 해당되지만...

C++에 대해서 아에 기초가 없으신 분들은 뭔 외계어인가 하며 

분노게이지가 차오르실 것입니다 ㅠㅠ...


아무튼... 시작해보도록 하겠습니다...



캡슐화에 대해서부터 썰을 풀도록 해보죠...

캡슐화는 우선 멤버 변수와 멤버 메소드가 한 class에 있는 모양을 가지고 있으며

public, private, protected 와 같은 접근 지정자를 사용할 수 있는 녀석입니다...


객체 지향 프로그래밍에서 재미있는 것은 

실제로 있는 사물? 혹은 어떤것에 대해서 분석하고 해당 대상에 무엇이 있는지

뽑아내어 실제 class로 구현을 하여 프로그램에 나타낼 수 있다는 것이죠...


아무튼... 캡슐화를 할 때에는 우선 캡슐화 할 대상에 대해 파악을 할줄 알아야합니다...

대상에 뭐가있는지... 조사를 한다면

멤버 필드(변수)와 멤버 메소드에 어떠한 것들이 만들어져야하는지

설계가되고 결과적으로 아름다운 캡슐이 하나 생기겠죠... 푸하하


멤버 필드와 같은 경우에는 왠만하면 목에 칼이 들어온다하여도...(...?!)

private으로 누구나 접근을 할 수 없도록 만들어

주요 요소들에 대한 값 변경 및 한치의 접근조차 용납하지 못하도록 만드는 것을 기준으로 해줍니다...


멤버 메서드같은 경우에는 default 가시성을 private로 지정하는것이 바람직하지만

멤버 메서드 중에서도 외부에 접근을 필요로 할 때에는 

public으로 지정해주는 것이 옳겠죠...


예를 들어 멤버 변수에 대한 값을 가져와야할 필요성이 있다면

굳이 멤버 변수를 public으로 접근 권한을 지정할 것이 아니라

public 형태의 메소드를 하나 만들어 멤버 변수의 값을 return 해줄 수 있는...

그정도? 하하


그리고 파생형식에서 기본 클래스에 접근을 필요로한다면 protected로 

형식을 지정해줘야겠죠....


이 말을 한문장으로 정리하자면,

멤버필드와 같은 경우에는 주요 데이터들이 저장될 것이기에 외부에 노출이 되어서는 안됩니다...

(한문장 정리 실패... 아무튼...)

따라서 멤버 메서드를 통해 외부에서 접근해야할 멤버를 return 해주는 형식으로 

가져오기 및 설정하기 기능을 제공하는 것이 바람직합니다...

멤버 변수를 다이렉트로 건들 수 있는 것이 아니라

간접적으로 값을 참조할 수 있도록 메서드를 통해 전달 하는 것이지요...


객체 지향에서 중요한 것중 하나는 정보은닉... 즉, '조금만 보여 주기'입니다...

다 보여줘봤자 위험 가능성만 커지기에....

신경쓰며 프로그래밍 공부를 해보자구요 아하하하하


죄송합니다... 여튼...

캡슐화를 공부하며 특이사항... 그러니 주의해야할 점에 대해서 생각해보자면

상수화(const) 멤버 필드(변수)를 명시해야할 것이 있는지 고민해야하는 것입니다...


상수화를 할 것을 생각하고 있지 않고 

마음가는데로... feeling 대로... 바람이 흐르는 대로....

작업을 하다가는 나중에 코딩하며 생각나는 멤버값이 실수로 변경이라도 된다면

프로그램이 꼬이고 꼬이며 스크류바가 되는 놀라운 경험을 체험하실 수 있겟죠...

그러니까... 설계과정에서 고민을 하라는 것입니다...


참고로 상수화 멤버 필드는 생성자 이니셜라이즈를 해줘야합니다...

반드시 생성자 이니셜라이즈를 통해 상수값을 지정해줘야합니다!!


또한 정적 멤버가 필요한지 고민해야합니다... 

학번과 같이 중복될 이유도 없고 누구나 반드시 하나씩은 가지고 있어야 하는 

멤버 필드가 있을 경우에 순차적으로 하나하나 발급해주면 되죠... 

굳이 객체마다 해당 학번을 생성할 때마다 초기화해주는 어리석은 짓을 하지말고

정적 멤버 필드로 명시하여 하나로 관리하는 것이 더욱 효율적일 것입니다...


참고로 정적 멤버필드는 클래스 정의문의 내부와 외부 둘다 선언해줘야합니다...

헤더에도... 소스코드에도... 잊지마시길...



다음으로 상속에 대해서 썰을 풀도록 해봅시다...


객체 지향에서 중요한 것중 하나가 바로 '조금만 보여 주기'라고 했는데요,

여기 또 하나가 추가됩니다... 바로 '공통점 묶기'입니다.


공통적인 형식/부분이 뭐가 있는지 조사하고 쫙 나열해본다고 가정해보져...

이 리스트들에서는 모두 확인을 해야하는 것이 바로 일반화에 부합하냐 입니다...


A is a B 라는 논리가 성립한다면, 이 리스트들은 공통점 묶기에 대하여

충분한 자격조건을 가지게 되죠...


자.. 일반화를 거쳐서 이제 기반 클래스(부모 클래스)를 만들게 된다면

쉽게 쉽게 공통적인 특성을 가지고 살을 붙여 파생 클래스들을 만들 수 있게 됩니다...


파생클래스에 대해서 생각해보도록 하죠...

파생 형식에는 기반 클래스 내의 모든 기능을 제공하기에 파생클래스에서 

똑같은 기능을 사용한다면 문제가 없지만,

부모 클래스로부터 받아온 구체적인 행위가 다를 경우에는 가상 메서드로 정의해야합니다...


뭔말이냐하면... 예를 들어 드래곤볼 보셨나요.... 갑자기 생각이... 풉...

손오공이 노란색 에네르기파를 쓴다고 가정해보죠...

근데 그의 아들인 손오반은 즉 손오공의 파생 형식이 되겠죠...

이 손오반은 에네르기파를 쏘면 빨간색 에네르기파를 쏩니다...


이와 같이 구체적인 행위가 달라진다면... 문제가 생기기에

부모클래스에서는 이미 virtual 이라는 키워드를 사용하여 가상메서드로 정의를 해야한다 이거죠...


만약에... 구체적인 행위가 모두 다르다면... 추상 메서드(순수 가상 메서드)로 정의하는 것이

바람직하다고 볼 수 있겠죠...


파생 클래스에서 부분적으로 다르지만 공통점이 있다면 

기반형식에 가상 메서드로 공통적인 부분을 구현하고 

무효화된 기반 형식의 메서드를 불러오면 됩니다...

기반 형식에서의 공통적인 부분을 사용할 때 무효화한 기방형식의 메서드를 호출하기 위해서는

기반형식 :: 메서드() 이 와 같이 사용할 수 있겠죠... 

손오공 :: 에네르기파() 이와 같이 말입니다...


일반화 관계의 여러 객체를 관리할 때에는 

기반 형식 타입으로 관리하는 것이 가장 효율적입니다...

이와 같이 관리하게 된다면, 같은 방법으로 제어할 수 있는 장점을 가지게 되죠...


단, 파생 형식에서만 제공하는 특정 기능을 호출할 때에는 하향 캐스팅을 사용할 수 있게됩니다...

하향 케스팅을 위해서는 dynamic_cast ~!!



하하... 객체 지향 프로그래밍을 하며...

음... 저는 C++을 배우며... 느끼고 중요하다고 생각하는 점을... 

듣고... 모아서 정리해봤습니다...


아무리 이렇게 키보드 워리어가 되고 입만 털면 뭐합니까...

프로그램을 잘 짜야되는데... 으흐흐... (마음 아픈 웃음입니다...)


아무튼... 모두 같이 열심히 달려보자구요~!


이상 삽잡이였습니다~!!!!