<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>soooh_42.log</title>
        <link>https://velog.io/</link>
        <description>42Seoul -soooh ~ 2022.04</description>
        <lastBuildDate>Sun, 15 May 2022 07:59:03 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>soooh_42.log</title>
            <url>https://images.velog.io/images/soooh_42/profile/5e00ef86-f41e-4d8b-bdf9-a63151a2c382/powerpuff girls bubbles aesthetic.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. soooh_42.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/soooh_42" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[웹기획] 회원가입 페이지 기획하며 고려할 부분]]></title>
            <link>https://velog.io/@soooh_42/%EC%9B%B9%EA%B8%B0%ED%9A%8D-%ED%9A%8C%EC%9B%90%EA%B0%80%EC%9E%85-%ED%8E%98%EC%9D%B4%EC%A7%80-%EA%B8%B0%ED%9A%8D%ED%95%98%EB%A9%B0-%EA%B3%A0%EB%A0%A4%ED%95%A0-%EB%B6%80%EB%B6%84</link>
            <guid>https://velog.io/@soooh_42/%EC%9B%B9%EA%B8%B0%ED%9A%8D-%ED%9A%8C%EC%9B%90%EA%B0%80%EC%9E%85-%ED%8E%98%EC%9D%B4%EC%A7%80-%EA%B8%B0%ED%9A%8D%ED%95%98%EB%A9%B0-%EA%B3%A0%EB%A0%A4%ED%95%A0-%EB%B6%80%EB%B6%84</guid>
            <pubDate>Sun, 15 May 2022 07:59:03 GMT</pubDate>
            <description><![CDATA[<p>원래 좀 더 괜찮은 제목이 있었는데 벨로그 이미지 업로드 오류가 나더니 결국 내 글도 사라졌다 하하하하! 나 얼른 게임하러 가고 싶다구요! 대충 정형돈짤</p>
<p>자.. 이번 주에는 웹 기획팀으로 첫 출근을 했다 바로 프로젝트에 투입되지 않고 진행 중인 프로젝트의 보조 역할로 일을 배우고 있다. 그러다 스토리보드 회원가입 페이지 수정을 하게 되었는데, 이제 나는 이런 프로세스에 대해서 고민을 해야 하니까 진지하게 고민을 해 봤다.</p>
<p>회원가입을 하며 제공하는 나의 정보들은 지금 사용하려는 서비스에 꼭 필요한 정보일까? 오늘 낮에 배달의 민족을 사용했으니 배달의 민족을 예시로 들겠다.</p>
<p>사실 배달의 민족 회원이 된 시기는 좀 지났기 때문에 내 정보를 어디까지 제공했는지 기억이 잘 안 나지만 확실한 것은 내 번호와 내 주소일 것이다. 배달 현황을 공유하고, 내가 있는 장소로 배달을 받기 위해 제공한 정보다. 내가 제공한 정보만으로도 우아한 형제들은 꽤 괜찮은 데이터를 추출 중일 것이다. 그 데이터를 기반으로 내가 좀 더 나은 서비스를 구성할 수 있을 것이고. </p>
<p>지금이야 이 정보를 어디에 쓰려고 하는지 짐작은 가지만 일반 사용자들은 내 정보를 어디에 쓰려고 하지? 싶은 경험이 있을 것이다. 아무리 명시를 한다고 해도 기억에 잘 안 남기도 하고, 뉴스에서는 개인 정보 노출이라는 헤드라인을 뽑아대니 저절로 개인 정보 제공에 보수적으로 굴 게 된다. 그렇다면 기획자가 제일 먼저 할 수 있는 것은 회원가입의 허들을 낮추는 것이다. </p>
<p>서비스를 위해 필수로 받아야 하는 정보와 꼭 필요한 것은 아니지만 받으면 좋은 정보를 구분한다. 필수 정보와 선택 정보 채널을 따로 만드는 것이다.</p>
<p>배달의 민족 앱 설치 후 최초 화면은 위치 제공 페이지다.
<img src="https://velog.velcdn.com/images/soooh_42/post/5510f603-46bf-4748-881a-b4ed9621183a/image.png" alt=""></p>
<p>음식을 시켰으니 받아야 하는 위치 제공은 필수다. 이 정보를 제공하지 않으면 배민 서비스를 이용할 수 없다. 그렇지만 당장 내 음식 취향을 배민에 제공한다고 해서 서비스에 지장이 생길까? 그건 아니다. 필수 정보는 주소, 선택 정보는 내 취향이다. </p>
<p>사실 배달의 민족은 가입하지 않아도 서비스를 이용할 수 있다. 배달 현황 공유를 위해 매번 번호 인증을 해야 하긴 하지만 말이다. 서비스 회사 입장에서도 비회원보다 회원의 데이터를 받는 것이 더 이득이기 때문에 (서비스 개선이나 데이터 통계 등) 회원수를 늘리는 것이 목적인데 이러한 회원 전환률을 위해 진행하는 마케팅이 있을 것이다.</p>
<p>비회원 주문을 할 때마다 번거로운 번호 인증 버튼 옆에 로그인을 하면 하지 않아도 된다는 문구나, 편리한 서비스인 배민 페이는 로그인 회원만 할 수 있다는 차별화 전략, 그리고 주문 버튼을 누름과 동시에 로그인하겠냐는 팝업창과 하단에 작게 표시된 비회원 주문하기 버튼이 회원가입을 유도하는 방식이다.
<img src="https://velog.velcdn.com/images/soooh_42/post/126b7398-b737-4f15-8a0c-75603adc8d74/image.png" alt=""></p>
<p>또 하나의 대표적인 마케팅 방식은 첫 주문 시 10000원 할인! 문구가 아닐까 생각한다. 비슷한 예로 친구 초대하고 5000원 할인 받기도 있다. 쿠폰 발급의 조건은 첫 주문자 + 배민 회원이다. 이후 진행하는 모든 쿠폰 이벤트는 회원을 대상으로 진행 중이기도 하다. 배민의 대항마인 요기요도 비슷한 마케팅을 진행했었다. 주문율을 높이기 위한 마케팅도 되지만 회원 전환에도 도움이 되는 마케팅이다.
<img src="https://velog.velcdn.com/images/soooh_42/post/a677e166-6dfc-4c6d-bc98-e7e456d6c553/image.png" alt=""></p>
<p>자 이제 사용자는 회원가입을 하려고 마음 먹었다고 하자. 이제 내가 너희에게 내 정보를 주겠다 생각을 하고 회원 가입 버튼을 눌렀는데 이 번거롭고 어질어질한 회원가입 페이지를 보니 부담스러워서 하기 싫어졌다면 어떻게 해야 할까? 
<img src="https://velog.velcdn.com/images/soooh_42/post/6b87a81b-3af7-4d0a-a02a-5b62f2dbe873/image.png" alt="">
출처 | <a href="https://germweapon.tistory.com/384">이렇게 기획하면 안 돼요! #회원가입</a></p>
<p>아무래도 스마트폰은 컴퓨터 화면보다 작아서 최대한 간략하게 기획하는 것이 사용자를 배려하는 페이지 기획이다. 우리는 이것을 1 thing 1 page라고 부르기로 했어요.</p>
<p>배달의 민족 회원가입 제일 첫 페이지이다. 1개의 페이지에 1개의 절차를 담았다. 
<img src="https://velog.velcdn.com/images/soooh_42/post/e3c5498f-71e6-4bb8-945b-d20a63af8fa3/image.png" alt=""></p>
<p>그리고 최대한 간략하게 진행하면 사용자는 번거롭지 않은 회원가입으로 서비스를 누릴 수 있고 필요한 정보만 제공할 수 있어 좋다. </p>
<p>사실 모든 서비스에 정보를 적게 받는 게 좋은 것만은 아니다. 스포티파이, 왓챠와 같은 나만의 취향을 제공하는 큐레이팅 서비스는 회원가입을 하며 취향을 담은 정보를 제공해야 내가 좋아하는 서비스를 누릴 수 있고, 틴더와 같은 데이팅앱도 내가 원하는 조건을 입력해야 개인화된 서비스를 받을 수 있다. 그렇다고 위에 언급한 예시처럼 입력창을 때려 박으라는 뜻은 아니고 오래 걸릴 것 같다면 남은 단계를 눈에 보여줌으로써 사용자가 루즈하지 않도록 유지하는 게 제일 좋을 것이다. </p>
<p>취업을 위해 원티드 서비스를 이용하며 좋았던 것은 이력서 작성 유도와 함께 자신들이 제공하는 이력서로 이력서를 제출하면 서류 통과율이 더 높았다는 메세지와 몇 자 이상 쓰니 멋진 기록을 가지고 있다는 칭찬이 나오니 더 열심히 작성하게 되었다. 내 정보를 받으면 받을 수록 좋은 서비스는 어떤 방식으로 정보를 유도할 것인지도 고민하면 좋을 것 같다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL] SwiftUI ]]></title>
            <link>https://velog.io/@soooh_42/TIL-SwiftUI</link>
            <guid>https://velog.io/@soooh_42/TIL-SwiftUI</guid>
            <pubDate>Sun, 01 May 2022 08:30:19 GMT</pubDate>
            <description><![CDATA[<h1 id="stack">Stack</h1>
<p>SwiftUi에서 사용하는 Stack의 종류는 3가지가 있는데 ZStack, HStack, VStack이다.</p>
<p>CS193p를 보며 카드 게임을 만들 수 있는데 제일 먼저 접한 Stack은 ZStack이었다.</p>
<h3 id="zstack">ZStack</h3>
<p>Gneric Structure, 요소를 오버레이하고 두 축으로 배열하는 뷰.
<img src="https://velog.velcdn.com/images/soooh_42/post/a835423d-b36d-438c-9b98-2190ad6ad004/image.png" alt=""></p>
<p>Text 4개를 겹쳤지만 화면에서는 하나로 보이는 상황. Stack이니 어딘가에 쌓여야 하는데 ZStack이라는 이름에 걸맞게 X, Y, Z 축으로 생각을 해 보면 Z축을 기준으로 Stack이 쌓인다고 보면 된다.</p>
<h3 id="vstack-hstack">VStack, HStack</h3>
<p>Vertical, Horisontal로 쌓이는 Stack이다.
<img src="https://velog.velcdn.com/images/soooh_42/post/2e6c75ad-4c62-4ee6-8e0d-abbe213ae5f7/image.png" alt="">
<a href="https://seons-dev.tistory.com/147">이미지 출처</a></p>
<p>HStack이랑 VStack은 가로 쌓기, 세로 쌓기의 차이라서 더 서술하지 않으려고 한다.</p>
<h1 id="scrollview">ScrollView</h1>
<p>화면의 Scroll 컨테이너를 쉽게 만들 수 있다. 내부에 배치한 내용에 맞게 자동으로 사이즈 조절이 가능하고, 안전 영역을 피하기 위해 필요한 요소도 자동으로 추가한다.</p>
<pre><code>ScrollView{
    LazyVGrid(columns: [GridItem(.adaptive(minimum: 65))]) {
        ForEach(emojis[0..&lt;emojiCount], id: \.self, content: { 
            emoji in CardView(content: emoji)
                .aspectRatio(2/3, contentMode: .fit)
         })
     }
}</code></pre><h1 id="spacer">Spacer</h1>
<p>이름처럼 빈 공간을 만든다. 다른 Object의 크기에 우선 순위를 두고 해당 오브젝트의 크기가 변하지 않는 선에서 본인의 크기를 최대한 늘리려는 성질이 있다.</p>
<pre><code>HStack {
    remove
    Spacer()
    add
}</code></pre><p><img src="https://velog.velcdn.com/images/soooh_42/post/53a04ac7-8617-49c2-a535-7b82cac9ac6b/image.png" alt=""></p>
<p>가로로 쌓은 Stack을 Spacer()를 넣으니 각각의 버튼이 끝과 끝으로 멀어졌다.</p>
<h1 id="sf-symbols">SF-Symbols</h1>
<p>위의 이미지에서 사용한 아이콘들은 아이폰 애플리케이션 UI에서 자주 쓰이는 아이콘인데 해당 아이콘을 모아둔 프로그램이 있다. </p>
<p><a href="https://developer.apple.com/sf-symbols/">https://developer.apple.com/sf-symbols/</a></p>
<p>애플에서 제공하는 프로그램이다. </p>
<p><img src="https://velog.velcdn.com/images/soooh_42/post/280cfe5a-4d95-4d1a-a13f-d04543cade00/image.png" alt=""></p>
<p>오른쪽 상단에 원하는 아이콘을 검색하면 여러 아이콘이 나온다.</p>
<p><img src="https://velog.velcdn.com/images/soooh_42/post/05741688-1fbe-4400-9be7-30c8549931fd/image.png" alt=""></p>
<pre><code>    var remove: some View {
        Button {
            if emojiCount &gt; 1 { emojiCount -= 1 }
        } label: {
            VStack {
                Image(systemName: &quot;minus.circle&quot;) ⬅️
            }
        }
    }
    var add: some View {
        Button {
            if emojiCount &lt; emojis.count { emojiCount += 1}
        } label: {
                VStack {
                     Image(systemName: &quot;plus.circle&quot;) ⬅️
            }
        }
    }</code></pre><p>⬅️ 표시 위치처럼 Image(systemName: &quot;{sf-symbols 이름}&quot; 으로 부여하면 된다. 사이즈 조절이나 색 부여도 가능하다</p>
<h1 id="foreach">ForEach</h1>
<p>카드 뒤집기 게임을 만들면서 아이콘 24개를 각 카드마다 부여를 해야 하는데 하나하나 지정하는 방법 말고 반복문을 통해 부여할 수 있다. C를 공부했을 때는 인자를 새로 선언해 반복문을 돌리는 게 번거로웠다면 SwiftUI에서는 스스로 본인 위치에 찾아가는 것 같은 느낌이었다.</p>
<p>일반적인 For과 ForEach가 다른 게 무엇이냐면 ForEach는 일종의 뷰 컨테이너처럼 작용하며, View를 계산해서 보여준다는 점이다.</p>
<pre><code>ForEach(0..&lt;10){ num in
    Text(&quot;Num: \(num)&quot;)
        .font(.largeTitle)
}</code></pre><p><img src="https://velog.velcdn.com/images/soooh_42/post/94ecd3c8-ca35-4eae-999b-9240c9eb4369/image.png" alt=""></p>
<p>Int값이 아닌 String 배열을 ForEach에 넣으면 어떻게 될까 아마 오류가 날 것이다. 굳이 String이 아닌 Int 배열을 넣어도 똑같이 오류가 날 것.</p>
<p>이유는 Identifiable 프로토콜 조건에 맞지 않는다고 하는데. 해당 조건은 데이터를 식별할 수 있는 무언가를 가지고 있어야 한다고 한다. 각 배열마다 id를 가지고 있어야 한다고 이해하면 되겠다. </p>
<p>그렇다면 이 id는 어떻게 부여해야 할까? 직접 부여하는 방법도 있지만 배열의 개수가 10개 이상이어도 굉장히 귀찮아지는 일이다.</p>
<p>ForEach에서는 배열 내의 각 요소에 id를 부여할 수 있는 방법을 제공하는데 </p>
<pre><code>ForEach(emojis[0..&lt;emojiCount], id: \.self, content: { emoji in
    CardView(content: emoji).aspectRatio(2/3, contentMode: .fit)
})</code></pre><p>\ .self 를 입력하면 배열에서 각각의 요소에 아이디를 부여한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[42Seoul] CPP Module 01 - ex06]]></title>
            <link>https://velog.io/@soooh_42/42Seoul-CPP-Module-01-ex06</link>
            <guid>https://velog.io/@soooh_42/42Seoul-CPP-Module-01-ex06</guid>
            <pubDate>Tue, 11 Jan 2022 16:59:19 GMT</pubDate>
            <description><![CDATA[<h2 id="switch">switch</h2>
<p><code>switch</code>문은 조건부 분기 문을 제공한다.</p>
<pre><code>void    testSwitch(int a)
{
    switch(a)
    {
        case 0:
        // do something...
        case 1:
        // do something...
        case 2:
        // do something...
    }
}</code></pre><p><code>switch</code> 표현시기 값을 평가하고, 각 <code>case</code>의 값과 같은지 테스트하고 같을 경우 해당 <code>case</code>안의 코드를 실행한다.</p>
<p>간단하게.. a가 a==0이면 case0부터 case2까지 실행할 수 있는 (break가 있으면 멈춤) 개꿀 함수가 되겠다.</p>
<p>main.cpp를 인자를 받는 식으로 바꾸고 해당 값과 ex05에서 한 것처럼 반복문을 통해 같은 level을 만나면 이후에 주어진 포인터의 level도 연속으로 실행을 한다.</p>
<pre><code class="language-cpp">int    flag = 0;
    for(int i = 0; i &lt; 4; i++)
    {
        if (levels[i] == level)
        {
            switch (i)
            {
                case 0:
                        (this-&gt;*funcs[0])();
                        flag++;
                case 1:
                        if (i != 1)
                            std::cout &lt;&lt; std::endl;
                        (this-&gt;*funcs[1])();
                        flag++;
                case 2:
                        if (i != 2)
                            std::cout &lt;&lt; std::endl;
                        (this-&gt;*funcs[2])();
                        flag++;
                case 3:
                        if (i != 3)
                            std::cout &lt;&lt; std::endl;
                        (this-&gt;*funcs[3])();
                        flag++;
            }
        }
    }
    if (flag == 0)
        std::cout &lt;&lt; &quot;[ Probably complaining about insignificant problems ]&quot; &lt;&lt;std::endl;</code></pre>
<p><img src="https://images.velog.io/images/soooh_42/post/337fefa8-2545-4027-ad5f-c87cfe525494/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-01-12%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%201.58.47.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[42Seoul] CPP Module 01 - ex05]]></title>
            <link>https://velog.io/@soooh_42/42Seoul-CPP-Module-01-ex05</link>
            <guid>https://velog.io/@soooh_42/42Seoul-CPP-Module-01-ex05</guid>
            <pubDate>Tue, 11 Jan 2022 16:57:54 GMT</pubDate>
            <description><![CDATA[<p>포인터를 선언하고 거기에 private 함수들을 넣고, 다른 포인터에는 level 리스트를 넣었다. </p>
<pre><code class="language-cpp">void    (Karen::*funcs[4])(void) = {
    &amp;Karen::debug,
    &amp;Karen::info,
    &amp;Karen::warning,
    &amp;Karen::error
};
std::string levels[4] = {
    &quot;DEBUG&quot;,
    &quot;INFO&quot;,
    &quot;WARNING&quot;,
    &quot;ERROR&quot;
};</code></pre>
<p>반복문을 통해<code>levels[i] == level</code>일 때<code>(this-&gt;*funcs[i])()</code>를 실행하면 된다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[42Seoul] CPP Module 01 - ex04]]></title>
            <link>https://velog.io/@soooh_42/42Seoul-CPP-Module-01-ex04</link>
            <guid>https://velog.io/@soooh_42/42Seoul-CPP-Module-01-ex04</guid>
            <pubDate>Tue, 11 Jan 2022 14:23:00 GMT</pubDate>
            <description><![CDATA[<h2 id="fstream-헤더">fstream 헤더</h2>
<p><code>fstream</code> 헤더는 c++에서의 파일 입출력 헤더이다.<code>std::cout</code>, <code>std::cin</code>과 유사하게 시프트 연산을 통해 사용할 수 있다.</p>
<p><code>fstream</code> 헤더에는 총 세 가지 클래스가 존재한다.</p>
<ol>
<li><code>ifstream</code></li>
<li><code>ofstream</code></li>
<li><code>fstream</code></li>
</ol>
<ol>
<li>파일 불러오기</li>
</ol>
<pre><code class="language-cpp">std::ifstream fin(filename);
    //파일 연결
    if (fin.fail())
    {
        std::cerr &lt;&lt; &quot;Error: No &#39;&quot; &lt;&lt; filename &lt;&lt; &quot;&#39; found&quot; &lt;&lt; std::endl;
        return (1);
    }</code></pre>
<ol start="2">
<li>파일 내용 출력해 보기</li>
</ol>
<pre><code class="language-cpp">char out;
    while (fin.get(out))
        std::cout &lt;&lt; out;</code></pre>
<ol start="3">
<li>s1문자열이 있는지 확인하기</li>
</ol>
<pre><code class="language-cpp">while (buf.find(s1) != std::string::npos)</code></pre>
<ol start="4">
<li>s1 내용을 s2 내용으로 바꾸기</li>
</ol>
<pre><code class="language-cpp">{
    index = buf.find(s1);
    buf.erase(index, s1.length());
    //s1지우고
    buf.insert(index, s2);
    //s2넣기
}</code></pre>
<ol start="5">
<li>해당 파일을 .replace 확장자 붙여서 출력하기</li>
</ol>
<pre><code class="language-cpp">std::ofstream fout(filename + &quot;.replace&quot;);
fout &lt;&lt; buf;</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[42Seoul] CPP Module 01 - ex03]]></title>
            <link>https://velog.io/@soooh_42/42Seoul-CPP-Module-01-ex03</link>
            <guid>https://velog.io/@soooh_42/42Seoul-CPP-Module-01-ex03</guid>
            <pubDate>Tue, 11 Jan 2022 13:55:28 GMT</pubDate>
            <description><![CDATA[<pre><code class="language-cpp">int main()
{
  {
    Weapon club = Weapon(&quot;crude spiked club&quot;);
    HumanA bob(&quot;Bob&quot;, club);
    bob.attack();
    club.setType(&quot;some other type of club&quot;);
    bob.attack();
  }
  {
    Weapon club = Weapon(&quot;crude spiked club&quot;);
    HumanB jim(&quot;Jim&quot;);
    jim.setWeapon(club);
    jim.attack();
    club.setType(&quot;some other type of club&quot;);
    jim.attack();
  }
}</code></pre>
<p>해당 과제에서는 main문이 주어진다. == main을 보고 필요함 함수를 파악해야 한다.</p>
<ul>
<li>club 객체의 setType 함수를 사용해도 Human 객체가 지니고 있는 Weapon의 type이 변경되므로, Human 클래스 내의 Weapon은 생성자는 setWeapon 함수를 통해 들어온 Weapon 객체가 저장된 메모리를 참조할 수 있어야 한다.</li>
<li>Human 클래스 내의 Weapon은 포인터나 참조자로 선언한다.</li>
<li>과제 규칙 중 HumanB는 Weapon이 NULL일 수도 있다는 의미이로 HumanB는 포인터로 선언.</li>
<li>club은 포인터 변수가 아니며, HumanA 생성자의 두번째 매개변수로 객체 자체를 받기 때문에 HumanA는 참조자로 선언한다.</li>
</ul>
<hr>
<p>HumanA, HumanB에서 사용하는 Weapon을 꺼내지 않고 setType을 통해 A, B에 저장된 Weapon 값이 변경되어야 한다.</p>
<p>setWeapon()나 HumanA 생성자에서는 포인터를 사용하지 않았으니 참조를 사용하고, HumanB는 weapon 타입 클래스 변수가 NULL이어야 하며, setWeapon을 통해 클래스를 세팅하기 때문에 포인터를 사용하였다.</p>
<p>HumanA에서 참조 변수를 초기화할 필요가 있을 경우 초기화 리스트를 사용한다.</p>
<h2 id="초기화-리스트">초기화 리스트</h2>
<pre><code class="language-cpp">HumanA::HumanA(std::string name, Weapon &amp;weapon)
{
    this-&gt;name = name;
    this-&gt;weapon = weapon;
}</code></pre>
<p>해당 내용으로 컴파일을 하면 오류가 난다. </p>
<p>선언과 동시에 초기화해야 한다는 참조자의 제약 사항이 있기 때문. 또한 참조 변수가 아니어도 Class가 const로 선언되었다면 같은 오류가 발생할 것이다. 기존에 사용하는 방식은 선언 후 대입하는 방식에 가깝기 때문에 밑의 내용과 같이 수정했다.</p>
<pre><code class="language-cpp">HumanA::HumanA(std::string name, Weapon &amp;weapon) : name(name), weapon(weapon)
{
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[42Seoul] CPP Module 01 - ex02]]></title>
            <link>https://velog.io/@soooh_42/42Seoul-CPP-Module-01-ex02</link>
            <guid>https://velog.io/@soooh_42/42Seoul-CPP-Module-01-ex02</guid>
            <pubDate>Tue, 11 Jan 2022 13:47:28 GMT</pubDate>
            <description><![CDATA[<h3 id="참조자">참조자</h3>
<p>변수는 할당된 메모리 공간에 붙여진 이름이다. 우리는 변수의 이름을 가지고 해당 메모리 공간에 접근이 가능하다. 참조자는 할당된 하나의 메모리 공간에 다른 이름을 붙이는 것을 말한다. 자신이 참조하는 변수를 대신할 수 있는 별명과 같은 것이다. </p>
<pre><code class="language-cpp">std::string    str = &quot;HI THIS IS BRAIN&quot;;
std::string    *stringPTR = &amp;str;
std::string    &amp;stringREF = str;

std::cout &lt;&lt; &quot;str = &quot; &lt;&lt; str &lt;&lt; std::endl;
std::cout &lt;&lt; &quot;stringPTR = &quot; &lt;&lt; *stringPTR &lt;&lt; std::endl;
std::cout &lt;&lt; &quot;stringREF = &quot; &lt;&lt; stringREF &lt;&lt; std::endl;
stringREF = &quot;HI THIS IS NOT BRAIN&quot;;
std::cout &lt;&lt; &quot;====================value change====================&quot; &lt;&lt; std::endl;
std::cout &lt;&lt; &quot;str = &quot; &lt;&lt; str &lt;&lt; std::endl;
std::cout &lt;&lt; &quot;stringPTR = &quot; &lt;&lt; *stringPTR &lt;&lt; std::endl;
std::cout &lt;&lt; &quot;stringREF = &quot; &lt;&lt; stringREF &lt;&lt; std::endl;</code></pre>
<p><img src="https://images.velog.io/images/soooh_42/post/fde84d2e-d402-49b2-84fc-4a208d1e0644/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-01-11%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2010.46.40.png" alt=""></p>
<p>stringREF은 str의 별명이며 같은 메모리 공간을 참조한다. 참조자를 통해 값을 변경하면 메모리 공간을 같이 쓰는 변수의 값도 변경된다.</p>
<h3 id="참조자와-포인터">참조자와 포인터</h3>
<p>참조자와 포인터는 유사한 점이 많은데, 참조자는 포인터를 잘못 사용해서 생길 수 있는 문제를 줄이기 위한 대안이며, 포인터보다 제약사항이 많다고 한다.</p>
<ul>
<li>포인터는 초기화 없이 선언이 가능하며, NULL로 초기화가 가능하다</li>
<li>참조자는 둘 다 불가능하다. 따라서 널 포인터 역참조 같은 문제를 사전에 방지할 수 있다.</li>
<li>또한 참조 대상의 주소에 접근할 수 있을 뿐, 참조 대상의 주소 자체를 바꾸는 것은 불가능하기 때문에 초기화된 이후로 참조대상을 변경할 수 없다.</li>
</ul>
<pre><code class="language-cpp">int    main()
{
    std::string    str = &quot;HI THIS IS BRAIN&quot;;
    std::string    *stringPTR = &amp;str;
    std::string    &amp;stringREF = str;

    std::cout &lt;&lt; &quot;=============================&quot; &lt;&lt; std::endl;
    std::cout &lt;&lt; &quot;           STRING            &quot; &lt;&lt; std::endl;
    std::cout &lt;&lt; &quot;=============================&quot; &lt;&lt; std::endl;
    std::cout &lt;&lt; &quot;str = &quot; &lt;&lt; str &lt;&lt; std::endl;
    std::cout &lt;&lt; &quot;stringPTR = &quot; &lt;&lt; *stringPTR &lt;&lt; std::endl;
    std::cout &lt;&lt; &quot;stringREF = &quot; &lt;&lt; stringREF &lt;&lt; std::endl;
    std::cout &lt;&lt; &quot;=============================&quot; &lt;&lt; std::endl;
    std::cout &lt;&lt; &quot;           ADDRESS           &quot; &lt;&lt; std::endl;
    std::cout &lt;&lt; &quot;=============================&quot; &lt;&lt; std::endl;
    std::cout &lt;&lt; &quot;str = &quot; &lt;&lt; &amp;str &lt;&lt; std::endl;
    std::cout &lt;&lt; &quot;stringPTR = &quot; &lt;&lt; stringPTR &lt;&lt; std::endl;
    std::cout &lt;&lt; &quot;stringREF = &quot; &lt;&lt; &amp;stringREF &lt;&lt; std::endl;
}</code></pre>
<p><img src="https://images.velog.io/images/soooh_42/post/c79adaf2-07c0-496e-8efc-5236342fec80/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-01-11%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2010.47.03.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[42Seoul] CPP Module 01 - ex01]]></title>
            <link>https://velog.io/@soooh_42/42Seoul-CPP-Module-01-ex01</link>
            <guid>https://velog.io/@soooh_42/42Seoul-CPP-Module-01-ex01</guid>
            <pubDate>Tue, 11 Jan 2022 13:45:17 GMT</pubDate>
            <description><![CDATA[<h3 id="객체-배열과-객체-포인터-배열">객체 배열과 객체 포인터 배열</h3>
<p>객체를 배열 넣는 방법은 두 가지가 있는데 <code>객체 배열</code>과 <code>객체 포인터 배열</code>이다.</p>
<pre><code class="language-cpp">// 객제 배열 선언
Zombie Zombies[10];
// 객체 포인터 배열 선언
Zombie *Zombies = new Zombie[10];</code></pre>
<p><strong><em>객체 배열</em></strong></p>
<p>객체 배열 선언 시 생성자도 호출되지만 생성자에 인자를 전달하지 못한다. 
원하는 값으로 초기화가 필요하다면 초기화 과정이 따로 필요하다.
객체 배열 생성 시 생성자가 호출되는 것이 확인된다, 배열 소멸 시 소멸자도 호출.</p>
<p><strong><em>객체 포인터 배열</em></strong></p>
<p>객체의 주소를 담는 방식. 선언 후 일일히 동적할당하여 반환된 객체의 주소값을 배열에 대입해 줘야 함.</p>
<h3 id="zombiehorde-함수"><code>zombieHorde</code> 함수</h3>
<p>N개의 Zombie를 한 번에 할당해야 하며 한 번에 삭제되어야 한다. 주소를 반환하라고 하지 않았으니 객체 배열로 만든다.</p>
<p>ex00에 사용한 함수를 그대로 재활용해도 된다는 조건에 추가 작업할 시간은 줄었는데 함수를 작성하고 보니 name이 그대로 사용되어 구분이 어려웠다.</p>
<p><img src="https://images.velog.io/images/soooh_42/post/3a55ef38-309d-4537-a6fa-cf9e5da8066f/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-01-11%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2010.43.31.png" alt=""></p>
<p>C에서 사용한 atoi처럼 c++에도 방법이 있을 것이라 판단해 찾아 보았다 itos라는 함수가 있었는데 해당 함수는 버전이 높아 지금 상황에서는 쓸 수 없었다. 직접 만들거나 다른 방법을 찾아야 했는데 <a href="https://psychoria.tistory.com/708">블로그</a>를 발견해 해당 방법을 찾았다</p>
<pre><code class="language-cpp">Zombie* zombieHorde( int N, std::string name )
{
    Zombie    *numzom = new Zombie[N];
    std::stringstream    ss;

    for (int i = 0; i &lt; N; i++)
    {
        ss &lt;&lt; i;
        numzom[i].setName(name + ss.str());
        numzom[i].announce();
        ss.str(&quot;&quot;);
    }
    return (numzom);
}</code></pre>
<p>방법은 간단하다. <code>i</code>로 들어온 <code>int</code> 값을 <code>ss</code>에 넣고, 해당 값을 <code>str()</code>형식으로 출력해 <code>setName</code>으로 <code>name</code>을 변경한다. </p>
<p>기본 생성자를 통해 인스턴스를 만들기 위해 기본 생성자를 명시했다. </p>
<p><img src="https://images.velog.io/images/soooh_42/post/a387991b-1a08-416a-a020-f00be0a8bf7c/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-01-11%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2010.44.01.png" alt=""></p>
<p><code>zombieHorde</code>에서 값을 초기화하지 않고 계속 값을 추가했더니 이렇게 됐다. 함수 사용에는 문제가 없지만 보기에 좋지 않아서 사용이 끝나면 초기화하는 방식으로 <code>ss.str(&quot;&quot;);</code> 을 작성했다. <code>stringstream</code> 사용법을 보며 <code>clear()</code>가 있어서 해당 함수가 초기화라고 생각했는데 <code>state</code>를 지우는 함수라고 했다. <code>stringstream</code>를 초기화하는 함수는 2개가 있다.</p>
<ol>
<li><code>ss.str(&quot;&quot;)</code>;</li>
<li><code>ss.str(std::string())</code>;</li>
</ol>
<p><img src="https://images.velog.io/images/soooh_42/post/882a4460-014f-4451-9067-8d34263b6be0/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-01-11%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2010.44.54.png" alt=""></p>
<p>이제 예쁘게 잘 나온다.</p>
<h3 id="setter">Setter</h3>
<pre><code class="language-cpp">void    Zombie::setName(std::string name)
{
    this-&gt;name = name;
}</code></pre>
<p>ex00의 조건 중에는 name을 private로 선언해야 했는데 <code>zombieHorde</code> 에서 Zombie 클래스의 name을 변경하는 것이 불가능하기 때문에 private로 선언된 변수를 변경하기 위해서는 클래스 내부에서 접근할 수 있는 public 함수로 새로 선언해야 한다. 이러한 것을 setter라고 부른다.</p>
<p>그렇다면 private가 아닌 public으로 선언하면 되는데 굳이 setter를 이용하는 이유는 무엇일까? CPP00에도 적었지만 외부에서 무분별하게 변수의 값을 설정하는 것을 막기 위해서다. setter를 통해 접근하면 예외처리가 가능하지만 변수로 바로 접근한다면 예외처리가 불가능하기 때문.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[42Seoul] CPP Module 01 - ex00]]></title>
            <link>https://velog.io/@soooh_42/42Seoul-CPP-Module-01-ex00</link>
            <guid>https://velog.io/@soooh_42/42Seoul-CPP-Module-01-ex00</guid>
            <pubDate>Tue, 11 Jan 2022 13:42:38 GMT</pubDate>
            <description><![CDATA[<h2 id="인스턴스를-생성하는-두-가지-방법">인스턴스를 생성하는 두 가지 방법</h2>
<pre><code class="language-cpp">Zombie stackZombie = Zombie(&quot;stackZombie&quot;);
Zombie *heapZombie = newZombie(&quot;heapZombie&quot;);</code></pre>
<p>1번은 stack에 할당, 2번은 heap에 할당하는 방식이다. heap에 할당하고 싶다면 <code>new</code>예약어와 <code>포인터</code> 변수를 사용하면 된다</p>
<p>stack과 heap을 익히기 전 메모리 구조에 대해 알면 더 좋다. 프로그램이 실행되기 위해서는 프로그램이 메모리에 로드가 되어야 하며, 프로그램에서 사용되는 변수들을 저장할 메모리도 필요하다.</p>
<p>따라서 컴퓨터의 운영체제는 프로그램의 실행을 위해 다양한 메모리 공간을 제공한다. 프로그램이 운영체제로부터 할당 받는 대표적인 메모리 공간은 4가지다.</p>
<ol>
<li>code, 2. data, 3. stack, 4. heap</li>
</ol>
<p><img src="http://tcpschool.com/lectures/img_c_memory_structure.png" alt="http://tcpschool.com/lectures/img_c_memory_structure.png"></p>
<h3 id="code">code</h3>
<p>실행할 프로그램의 코드가 저장되는 영역이다. text영역이라고도 함. CPU는 코드 영역에 저장된 명령어를 하나씩 가져가서 처리함. </p>
<h3 id="data">data</h3>
<p>프로그램의 전역 변수와 정적 변수가 저장되는 영역이다. 데이터 영역은 프로그램의 시작과 함께 할당되며 프로그램이 종료되면 소멸한다.</p>
<h3 id="stack">stack</h3>
<p>함수의 호출과 관계되는 지역 변수와 매개변수가 저장된다. </p>
<p>stack영역은 함수의 호출과 함께 할당되며, 함수의 호출이 완료되면 소멸한다. stack에 저장되는 함수의 호출 정보를 stack frame이라고 함.</p>
<p>stack영역은 push로 데이터를 저장하고, pop으로 데이터를 인출한다. 이러한 stack은 후입선출 방식에 따라 동작하기 때문에 가장 늦게 저장된 데이터가 가장 먼저 pop된다.</p>
<p>stack영역은 메모리의 높은 주소에서 낮은 주소의 방향으로 할당됨.</p>
<hr>
<p>런타임 시점에서 크기가 결정된다</p>
<p>LIFO 구조이다 (LIFO == 후입선출 <strong>L</strong>ast <strong>I</strong>n, <strong>F</strong>irst <strong>O</strong>ut)</p>
<p>선언한 함수 영역을 벗어나면 자동으로 소멸</p>
<p><code>.</code> 연산자를 통해 접근</p>
<h3 id="heap">heap</h3>
<p>사용자가 직접 관리할 수 있고, 그래야만 하는 메모리 영역이다. 사용자에 의해 메모리 공간이 동적으로 할당되고 해제된다. </p>
<p>heap영역은 메모리의 낮은 주소에서 높은 주소의 방향으로 할당된다.</p>
<hr>
<p>컴파일 시점에서 크기가 결정된다</p>
<p>동적 메모리 할당을 통해 저장되는 영역</p>
<p>힙 영역은 모든 프로세스에서 동적으로 로드된 모듈에서 공유된다</p>
<p><code>-&gt;</code> 연산자를 통해 인스턴스에 접근</p>
<p>사용이 종료된 시점에서 할당을 해제하지 않으면 메모리 릭이 발생</p>
<h2 id="stack과-heap의-장단점">stack과 heap의 장단점</h2>
<h3 id="stack-1">stack</h3>
<ul>
<li>매우 빠른 엑세스</li>
<li>변수를 명시적으로 할당 해제하지 않아도 된다</li>
<li>공간은 cpu에 의해 효율적으로 관리되며 메모리는 단편화 되지 않는다.</li>
<li>지역 변수만 사용한다</li>
<li>stack 크기가 os에 따라 제한된다</li>
<li>변수의 크기를 조정할 수 없다</li>
</ul>
<h3 id="heap-1">heap</h3>
<ul>
<li>변수를 전역적으로 액세스 할 수 있다</li>
<li>메모리 크기 제한 없다</li>
<li>상대적으로 느린 액세스</li>
<li>호율적인 공간 사용을 보장하지 못하면 메모리 블록이 할당된 후 시간이 지남에 따라 메모리가 조각화되어 해제될 수 있다</li>
<li>메모리를 직접 관리해야 한다(변수 할당, 해제는 직접)</li>
<li>c에서는 realloc, c++에서는 new (java도 new)</li>
</ul>
<h2 id="newzombie-vs-randomchump"><code>newZombie</code> vs <code>randomChump</code></h2>
<p><code>newZombie</code> 함수는, 다른 곳에서도 생성한 좀비 인스턴스를 사용할 수 있어야하므로 힙영역에 인스턴스를 생성하는 것이 적절하고, <code>randomChump</code> 함수 같은 경우는 함수 내에서 인스턴스가 자신의 역할을 전부 수행하기 때문에 스택영역에 할당해도 무방하다.</p>
<h1 id="maincpp">main.cpp</h1>
<pre><code class="language-cpp">const    std::string NAME[] =
{
    &quot;zombie00&quot;,
    &quot;zombie01&quot;,
    &quot;zombie02&quot;,
    &quot;zombie03&quot;
};

int    main(void)
{
    Zombie stackZombie = Zombie(&quot;stackZombie&quot;);

    Zombie *heapZombie = newZombie(&quot;heapZombie&quot;);
    delete heapZombie;

    for (int i = 0; i &lt; 4; i++)
    {
        randomChump(NAME[i]);
    }
}</code></pre>
<p><img src="https://images.velog.io/images/soooh_42/post/fa3b1d3a-fea7-4881-9a46-0f84bdda1752/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-01-11%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2010.42.04.png" alt=""></p>
<ol>
<li><code>stackZombie</code>는 stack에 할당되었기 때문에 따로 해제를 하지 않아도 프로그램 종료와 함께 소멸한다</li>
<li><code>heapZombie</code>는 heap에 할당되었으며 <code>delete heapZombie</code> 으로 직접 소멸을 명령했다</li>
<li>반복문으로 <code>randomChump</code> 함수를 실행시켰으며 1번과 같이 stack 영역에 할당해 함수 내 인스턴스가 자신의 역할을 모두 수행했기 때문에 자동으로 소멸된다.</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[42Seoul] CPP Module 00 - ex02]]></title>
            <link>https://velog.io/@soooh_42/42Seoul-CPP-Module-00-ex02</link>
            <guid>https://velog.io/@soooh_42/42Seoul-CPP-Module-00-ex02</guid>
            <pubDate>Sun, 02 Jan 2022 16:56:11 GMT</pubDate>
            <description><![CDATA[<ul>
<li><p>Exercise02 : The Job Of Your Dreams</p>
<p>  서브젝트에서 제공하는 <code>Account.hpp</code>와 <code>main</code> 이 포함된 <code>test.cpp</code> 를 제공함. <code>19920104_091532.log</code> 를 참고하여 <code>Account.cpp</code> 를 작성할 것.</p>
</li>
</ul>
<h3 id="accounthpp">Account.hpp</h3>
<pre><code class="language-cpp">// ************************************************************************** //
//                                                                            //
//                Account.hpp for GlobalBanksters United                //
//                Created on  : Thu Nov 20 19:43:15 1989                      //
//                Last update : Wed Jan 04 14:54:06 1992                      //
//                Made by : Brad &quot;Buddy&quot; McLane &lt;bm@gbu.com&gt;                  //
//                                                                            //
// ************************************************************************** //

#pragma once
#ifndef __ACCOUNT_H__
#define __ACCOUNT_H__

// ************************************************************************** //
//                               Account Class                                //
// ************************************************************************** //

class Account {

public:

    typedef Account        t;

    static int    getNbAccounts( void );
    static int    getTotalAmount( void );
    static int    getNbDeposits( void );
    static int    getNbWithdrawals( void );
    static void    displayAccountsInfos( void );

    Account( int initial_deposit );
    ~Account( void );

    void    makeDeposit( int deposit );
    bool    makeWithdrawal( int withdrawal );
    int        checkAmount( void ) const;
    void    displayStatus( void ) const;

private:

    static int    _nbAccounts;
    static int    _totalAmount;
    static int    _totalNbDeposits;
    static int    _totalNbWithdrawals;

    static void    _displayTimestamp( void );

    int                _accountIndex;
    int                _amount;
    int                _nbDeposits;
    int                _nbWithdrawals;

    Account( void );

};

// ************************************************************************** //
// vim: set ts=4 sw=4 tw=80 noexpandtab:                                      //
// -*- indent-tabs-mode:t;                                                   -*-
// -*- mode: c++-mode;                                                       -*-
// -*- fill-column: 75; comment-column: 75;                                  -*-
// ************************************************************************** //

#endif /* __ACCOUNT_H__ */</code></pre>
<h3 id="testcpp">test.cpp</h3>
<pre><code class="language-cpp">// ************************************************************************** //
//                                                                            //
//                tests.cpp for GlobalBanksters United                        //
//                Created on  : Thu Nov 20 23:45:02 1989                      //
//                Last update : Wed Jan 04 09:23:52 1992                      //
//                Made by : Brad &quot;Buddy&quot; McLane &lt;bm@gbu.com&gt;                  //
//                                                                            //
// ************************************************************************** //

#include &lt;vector&gt;
#include &lt;algorithm&gt;
#include &lt;functional&gt;
#include &quot;Account.hpp&quot;

int        main( void ) {

    typedef std::vector&lt;Account::t&gt;                              accounts_t;
    typedef std::vector&lt;int&gt;                                  ints_t;
    typedef std::pair&lt;accounts_t::iterator, ints_t::iterator&gt; acc_int_t;

    int    const                amounts[]    = { 42, 54, 957, 432, 1234, 0, 754, 16576 };
    size_t const            amounts_size( sizeof(amounts) / sizeof(int) );
    accounts_t                accounts( amounts, amounts + amounts_size );
    accounts_t::iterator    acc_begin    = accounts.begin();
    accounts_t::iterator    acc_end        = accounts.end();

    int    const            d[]            = { 5, 765, 564, 2, 87, 23, 9, 20 };
    size_t const        d_size( sizeof(d) / sizeof(int) );
    ints_t                deposits( d, d + d_size );
    ints_t::iterator    dep_begin    = deposits.begin();
    ints_t::iterator    dep_end        = deposits.end();

    int    const            w[]            = { 321, 34, 657, 4, 76, 275, 657, 7654 };
    size_t const        w_size( sizeof(w) / sizeof(int) );
    ints_t                withdrawals( w, w + w_size );
    ints_t::iterator    wit_begin    = withdrawals.begin();
    ints_t::iterator    wit_end        = withdrawals.end();

    Account::displayAccountsInfos();
    std::for_each( acc_begin, acc_end, std::mem_fun_ref( &amp;Account::displayStatus ) );

    for ( acc_int_t it( acc_begin, dep_begin );
          it.first != acc_end &amp;&amp; it.second != dep_end;
          ++(it.first), ++(it.second) ) {

        (*(it.first)).makeDeposit( *(it.second) );
    }

    Account::displayAccountsInfos();
    std::for_each( acc_begin, acc_end, std::mem_fun_ref( &amp;Account::displayStatus ) );

    for ( acc_int_t it( acc_begin, wit_begin );
          it.first != acc_end &amp;&amp; it.second != wit_end;
          ++(it.first), ++(it.second) ) {

        (*(it.first)).makeWithdrawal( *(it.second) );
    }

    Account::displayAccountsInfos();
    std::for_each( acc_begin, acc_end, std::mem_fun_ref( &amp;Account::displayStatus ) );

    return 0;
}

// ************************************************************************** //
// vim: set ts=4 sw=4 tw=80 noexpandtab:                                      //
// -*- indent-tabs-mode:t;                                                   -*-
// -*- mode: c++-mode;                                                       -*-
// -*- fill-column: 75; comment-column: 75;                                  -*-
// ************************************************************************** //</code></pre>
<h3 id="accountcpp">Account.cpp</h3>
<pre><code class="language-cpp">void    Account::_displayTimestamp(void)
{
}

void Account::displayAccountsInfos()
{
}

Account::Account(int initial_deposit)
{
}

void    Account::displayStatus( void ) const
{
}

void Account::makeDeposit( int deposit )
{
}

bool Account::makeWithdrawal( int withdrawal )
{
}

Account::~Account()
{
}</code></pre>
<p>hpp에 선언된 함수들이 test.cpp에서 어떻게 출력이 되는지 확인하기 위해 함수 선언만 냅다 넣은 후 cmd 로그를 출력했다.</p>
<p><img src="https://images.velog.io/images/soooh_42/post/2ba39356-b5c5-4b84-b255-79c23fd0fdae/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-01-03%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%201.54.41.png" alt=""></p>
<p>이제 저 함수 순서에 맞게 log 파일을 비교하며 만들 것이다.</p>
<pre><code class="language-cpp">void    Account::_displayTimestamp(void)
{
    time_t    t_stamp;
    char    buff[16];

    time(&amp;t_stamp);
    strftime(buff, sizeof(buff), &quot;%Y%m%d_%H%M%S&quot;, localtime(&amp;t_stamp));
    std::cout &lt;&lt; &quot;[&quot; &lt;&lt; buff &lt;&lt; &quot;]&quot;;
}</code></pre>
<p>log파일에 있는 시간 그대로 출력해야 하는 건가? 싶었는데 그냥 프로그램 실행 시간을 출력하면 돼서 ctime의 함수인 time()을 활용하기로 했다. time_t 구조체(시간을 다루는데 필요한 정보가 저장됨)에 time()으로 초 단위의 시간을 부여하고, strftime()으로 원하는 출력 양식으로 표현할 수 있다. 해당 함수로 time_t를 지정한 양식으로 변환시켜주는 기능이다. (<a href="https://modoocode.com/122">참고</a>) localtime()으로 초 단위의 시간을 현재 시간으로 출력했다.</p>
<pre><code class="language-cpp">Account::Account(int initial_deposit)
{
    _accountIndex = Account::_nbAccounts;
    _amount = initial_deposit;
    _nbDeposits = 0;
    _nbWithdrawals = 0;
    _displayTimestamp();
    std::cout &lt;&lt; &quot; index:&quot; &lt;&lt; _accountIndex &lt;&lt; &quot;;&quot;;
    std::cout &lt;&lt; &quot;amount:&quot; &lt;&lt; _amount &lt;&lt; &quot;;&quot;;
    std::cout &lt;&lt; &quot;created&quot; &lt;&lt; std::endl;
    Account::_nbAccounts++;
    Account::_totalAmount += _amount;
}</code></pre>
<p>log의 제일 첫 부분을 담당한다. 정보들을 생성했음을 알리는 함수다. </p>
<pre><code class="language-cpp">void Account::displayAccountsInfos()
{
    _displayTimestamp();
    std::cout &lt;&lt; &quot; accounts:&quot; &lt;&lt; Account::_nbAccounts &lt;&lt; &quot;;&quot;;
    std::cout &lt;&lt; &quot;total:&quot; &lt;&lt; Account::_totalAmount &lt;&lt; &quot;;&quot;;
    std::cout &lt;&lt; &quot;deposits:&quot; &lt;&lt; Account::_totalNbDeposits &lt;&lt; &quot;;&quot;;
    std::cout &lt;&lt; &quot;withdrawals:&quot; &lt;&lt; Account::_totalNbWithdrawals &lt;&lt; std::endl;
}</code></pre>
<p><code>[20220103_011945] accounts:8;total:20049;deposits:0;withdrawals:0</code> 으로 중간 집계 느낌으로 출력되는 내용이 있다. 어.. getter로 접근하라는 것 같았지만 까먹었다..^^! </p>
<pre><code class="language-cpp">void Account::makeDeposit( int deposit )
{
    int    p_amount;

    p_amount = _amount;
    _amount += deposit;
    _nbDeposits++;
    _displayTimestamp();
    std::cout &lt;&lt; &quot; index:&quot; &lt;&lt; _accountIndex &lt;&lt; &quot;;&quot;;
    std::cout &lt;&lt; &quot;p_amount:&quot; &lt;&lt; p_amount &lt;&lt; &quot;;&quot;;
    std::cout &lt;&lt; &quot;deposits:&quot; &lt;&lt; deposit &lt;&lt; &quot;;&quot;;
    std::cout &lt;&lt; &quot;amount:&quot; &lt;&lt; _amount &lt;&lt; &quot;;&quot;;
    std::cout &lt;&lt; &quot;nb_deposits:&quot; &lt;&lt; _nbDeposits &lt;&lt; std::endl;
    Account::_totalNbDeposits++;
    Account::_totalAmount += deposit;
}</code></pre>
<p><code>deposit</code> 값이 들어오면서 <code>amount</code> 값에 변동이 생겼다.
<code>인덱스; 금액; 예치금; 금액 + 예치금; 예치금 횟수;</code> 로 이해했으니 새로운 인자 <code>p_amount</code>을 선언해 함수를 만들었다. <code>displayAccountsInfos</code>에서 활용하기 위해 <code>total</code>인자도 값을 부여.</p>
<pre><code class="language-cpp">bool Account::makeWithdrawal( int withdrawal )
{
    int    p_amount;

    p_amount = _amount;
    _amount = _amount - withdrawal;
    _displayTimestamp();
    std::cout &lt;&lt; &quot; index:&quot; &lt;&lt; _accountIndex &lt;&lt; &quot;;&quot;;
    std::cout &lt;&lt; &quot;p_amount:&quot; &lt;&lt; p_amount &lt;&lt; &quot;;&quot;;
    if (_amount &gt;= 0)
    {
        _nbWithdrawals++;
        std::cout &lt;&lt; &quot;withdrawal:&quot; &lt;&lt; withdrawal &lt;&lt; &quot;;&quot;;
        std::cout &lt;&lt; &quot;amount:&quot; &lt;&lt; _amount &lt;&lt; &quot;;&quot;;
        std::cout &lt;&lt; &quot;nb_withdrawals:&quot; &lt;&lt; _nbWithdrawals &lt;&lt; std::endl;
        _totalNbWithdrawals++;
        Account::_totalAmount -= withdrawal;
        return (true);
    }
    else
    {
        std::cout &lt;&lt; &quot;withdrawal:refused&quot; &lt;&lt; &quot;;&quot; &lt;&lt; std::endl;
        _amount = p_amount;
        return (false);
    }
}</code></pre>
<p><code>인덱스; 원금; 회수액; 원금 - 회수액; 회수 횟수;</code> 함수 선언이 <code>boolen</code>으로 되어있고, <code>원금 - 회수액</code>이 <code>0</code>보다 클 때, 작을 때의 출력 문구도 다르기 때문에 조건문으로 각 반환 값을 <code>true</code>, <code>false</code>로 나눴다. </p>
<pre><code class="language-cpp">Account::~Account()
{
    _displayTimestamp();
    std::cout &lt;&lt; &quot; index:&quot; &lt;&lt; _accountIndex &lt;&lt; &quot;;&quot;;
    std::cout &lt;&lt; &quot;amount:&quot; &lt;&lt; _amount &lt;&lt; &quot;;&quot;;
    std::cout &lt;&lt; &quot;closed&quot; &lt;&lt; &quot;;&quot; &lt;&lt; std::endl;
}</code></pre>
<p>모든 프로그램을 마무리 하는 함수다. 남은 금액을 출력하면 돼서 생각한대로 출력을 했지만</p>
<p><img src="https://images.velog.io/images/soooh_42/post/df812880-7814-410f-a41e-ca46ef0b8f52/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-01-03%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%201.55.34.png" alt=""></p>
<p>예시로 받은 log와 출력 값이 달라서 살짝 멘붕이었다. 슬랙과 여러 블로그를 보며 이유를 알 수 있었는데. 간단히 설명하면 시스템 사양이 달라서, 설명을 곁들이자면 맥에서는 vector 안에서의 소멸 순서는 vextor가 구현된 표준 라이브러리에 따라 다르기 때문이다. 까먹지 말고 평가할 때 말해야겠다..</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[42Seoul] CPP Module 00 - ex01]]></title>
            <link>https://velog.io/@soooh_42/42Seoul-CPP-Module-00-ex00-xv7eiqfu</link>
            <guid>https://velog.io/@soooh_42/42Seoul-CPP-Module-00-ex00-xv7eiqfu</guid>
            <pubDate>Sat, 01 Jan 2022 17:01:30 GMT</pubDate>
            <description><![CDATA[<h2 id="exercise01">Exercise01</h2>
<ul>
<li><p>Exercise01 : My Awesome PhoneBook</p>
<p>  다음과 같은 조건을 만족하는 전화번호부 프로그램을 작성하라.</p>
<ul>
<li><p>동적 할당을 하지 않고 최대 8개의 연락처를 저장할 수 있다.</p>
</li>
<li><p>프로그램의 명령은 EXIT, ADD, SEARCH만 인식하며, 그 외의 경우는 모두 무시한다.</p>
</li>
<li><p>EXIT프로그램이 종료되며 모든 연락처가 삭제된다.</p>
</li>
<li><p>ADD연락처의 모든 정보가 채워질 때 까지 표준입력을 통해 정보를 입력받는다.</p>
<ul>
<li>연락처의 정보는 : first name, last name, nickname, phone number, darkest secret으로 구성되어 있다.</li>
<li>전화번호부 클래스는 연락처 배열을 포함해야 한다.</li>
<li>연락처는 반드시 코드에서 클래스의 인스턴스로 구현되어야 한다.</li>
<li>만약 전화번호부에 8개의 연락처가 모두 차 있는 경우, 가장 마지막에 있는 연락처를 지우고 새로운 연락처를 해당 인덱스에 넣어야 한다.</li>
</ul>
</li>
<li><p>SEARCH전화번호부 프로그램은 비어있지 않은 연락처의 4개 열을 출력한다 : index, first name, last name, nickname</p>
<ul>
<li>각 열의 너비는 10글자이며, 우측 정렬이고, 각 열은 <code>|</code> 기호로 분리된다. 또한 10글자를 초과한 항목의 경우 항목 + <code>.</code>을 10글자 길이로 맞추어 출력한다.</li>
<li>index를 추가로 입력할 시 해당 연락처의 모든 정보를 출력한다. 입력이 이상할 경우 특정 동작을 정의해야 한다.</li>
</ul>
<p>해당 과제에서는 클래스라는 새로운 개념을 학습해야 한다.</p>
</li>
</ul>
</li>
</ul>
<h3 id="class">Class</h3>
<p>구조체 선언과 마찬가지로 클래스 선언은 메모리에 할당되지 않는다. 
클래스가 어떻게 보이는지만 정의한다. 
클래스를 사용하려면 해당 클래스 타입의 변수를 선언해야 한다.</p>
<p>데이터를 보유하는 것 외에도 클래스에는 함수가 포함될 수 있다. 
클래스 내부에 선언된 함수를 <code>멤버 함수</code>라고 한다 == 메소드라고 불리기도 한다.
멤버 함수는 클래스 정의의 내부 또는 외부에서 정의할 수 있다. 해당 예제는 내부에 정의.</p>
<pre><code class="language-cpp">struct DateStruct 
{ 
    int year; 
    int month;
    int day; 
};

class DateClass 
{ 
    public:
        int m_year; 
        int m_month;
        int m_day; 

    void print()
    { 
        std::cout &lt;&lt; m_year &lt;&lt; &quot;/&quot; &lt;&lt; m_month &lt;&lt; &quot;/&quot; &lt;&lt; m_day; 
    }
};</code></pre>
<pre><code class="language-cpp">int main() 
{ 
    DateClass birthDay { 2019, 7, 28 }; 

    birthDay.m_year = 1992; // 클래스의 멤버 변수 접근, 값 수정 
    birthDay.print(); // 클래스의 멤버 함수 호출 return 0; 
}
</code></pre>
<p>구조체의 멤버처럼 클래스의 멤버는 멤버 선택 연산자 <code>.</code> 를 통해 접근할 수 있다.</p>
<p><code>DateClass.printf()</code>를 호출하면 <code>m_year</code>을 <code>DateClass.m_year</code>로 해석한다.
연관된 객체가 암시적으로 멤버 함수에 전달이 되는 것을 <strong>암시적 개체</strong>라고 한다.</p>
<p>멤버 함수가 항상 작업할 클래스의 암시적 객체를 가지고 있다는 것이 중요</p>
<h3 id="접근지정자">접근지정자</h3>
<ul>
<li><code>private</code> : 클래스 내부에서만 접근 가능.</li>
<li><code>public</code> : 클래스 내부뿐만 아니라 외부에서도 접근 가능.</li>
</ul>
<p>해당 클래스를 제외한 클래스, 해당 클래스 멤버 함수를 제외한 다른 함수를 의미한다. 만약 클래스 외부에서 <code>private</code> 으로 선언된 변수에 접근하고 싶다면 <code>getter</code>, <code>setter</code> 함수를 이용해야한다.
<code>private</code> 로 선언하는 것은 정보를 감추거나 무분별한 변수의 값 변경을 막기 위해.</p>
<h3 id="생성자constructor">생성자<strong>(Constructor)</strong></h3>
<p>클래스의 모든 멤버 변수가 <code>public</code>인 경우 <em>초기화 목록</em> 또는 <em>유니폼 초기화</em>를 사용해 초기화할 수 있다. 그러나 멤버 변수가 <code>private</code> 인 경우에는 변수에 직접 접근할 수 없는 비공개 상태이므로 더는 위와 같은 방법으로는 클래스를 초기화할 수 없다.</p>
<p>생성자는 해당 클래스의 객체가 인스턴스화될 때 자동으로 호출되는 특수한 종류의 멤버 함수.
일반적으로 클래스의 멤버 변수를 적절한 기본값 또는 사용자 제공 값으로 초기화하거나 클래스를 사용하는 설정이 필요한 경우 사용된다.</p>
<p><strong>생성자 정의 방법 규칙</strong></p>
<ul>
<li>생성자 이름은 클래스와 이름이 같아야 한다</li>
<li>생성자는 리턴 타입이 없다 (void도 아니다)</li>
</ul>
<pre><code class="language-cpp">class ClassName
{
public:
    int i;
    int j;
    ClassName()
    {
        std::cout &lt;&lt; &quot;생성자 테스트 문구입니다\n&quot;;
    };
    ClassName(int i, int j)
    {
        //code
    };
    ClassName(int i)
    {
        //code
    };
    ClassName(int j)
    {
        //code
    };
    ~ClassName();
};</code></pre>
<p>class 선언 후 class명과 같은 이름의 생성자를 정의한다. 생성자는 여러 개의 매개변수를 가질 수 있고, 오버로딩을 지원하기 때문에 위와 같이 선언할 수 있다.</p>
<p>~Contact()</p>
<p>디폴트 생성자 앞에 <code>~</code>을 붙인 형태. 매개 변수가 없다.</p>
<p>인스턴스의 사용이 끝나고 소멸될 때(메모리 반환) 자동으로 호출되는 코드</p>
<pre><code class="language-cpp">int main()
{
    ClassName name;
    ClassName *pName = new Name;
    return 0;
}</code></pre>
<pre><code class="language-cpp">//=====[output]=====//
&gt;&gt; 생성자 테스트 문구입니다
&gt;&gt; 생성자 테스트 문구입니다</code></pre>
<p><a href="https://devjh.tistory.com/97">참고</a></p>
<h3 id="프로그램-규칙">프로그램 규칙</h3>
<ol>
<li>프로그램은 사용자의 커맨드 입력을 대기하고 있다.</li>
<li>유효한 명령은 <code>EXIT</code>, <code>ADD</code>, <code>SEARCH</code> 3가지이다.<ul>
<li><code>EXIT</code> : 프로그램 종료</li>
<li><code>ADD</code> : Contact의 필드를 하나씩 입력받아, PhoneBook에 Contact를 하나 추가(연락처의 저장은 최대 8개까지 가능하며, 8개를 넘으면 가장 오래전에 저장된 연락처가 삭제)</li>
<li><code>SEARCH</code> : index를 입력받아 해당 index에 대응되는 연락처를 출력</li>
</ul>
</li>
<li>명령이 실행된 이후에는 다른 명령어 입력을 대기하고 있다.</li>
</ol>
<h3 id="phonebookcpp">Phonebook.cpp</h3>
<pre><code class="language-cpp">int    main(void)
{
    std::string    cmd;
    Contact contact;

    std::cout &lt;&lt; &quot;📞 Hello~ This is soooh Phonebook&quot; &lt;&lt; std::endl;
    std::cout &lt;&lt; &quot;Save Contact   : ADD&quot;&lt;&lt; std::endl;
    std::cout &lt;&lt; &quot;Search Contact : SEARCH&quot;&lt;&lt; std::endl;
    std::cout &lt;&lt; &quot;Contact End    : EXIT&quot;&lt;&lt; std::endl;
    while (true)
    {
        std::cout &lt;&lt; &quot;COMMAND        : &quot;;
        std::cin &gt;&gt; cmd;
        if (cmd == &quot;ADD&quot;)
            contact.Add();
        else if (cmd == &quot;SEARCH&quot;)
            contact.Search();
        else if (cmd == &quot;EXIT&quot;)
            return (0);
        else
            std::cout &lt;&lt; &quot;===== Wrong input =====&quot; &lt;&lt; std::endl;
        std::cin.clear();
        std::cin.ignore(1000, &#39;\n&#39;);
        if (std::cin.eof())
            return (0);
    }
}</code></pre>
<p>EXIT 입력하거나 eof 데이터가 없을 때까지 반복문
cin으로 입력 받으려고 할 때 EOF(End Of File)이라면 입력이 취소되며 이때 반환값은 true이다. 
이를 이용해 파일이 종료될 때까지 입력 받는 코드를 작성할 수 있다. (터미널에서는 수동 입력으로 해야 함 ctrl + D) <a href="https://www.acmicpc.net/board/view/24867">참고</a></p>
<p>cin을 통해 문자와 숫자를 입력 받을 때 저장되는 방식이 다르다. </p>
<p>문자: 입력 버퍼에 저장 후 해당 값을 읽어 변수에 저장
숫자: 바로 변수에 저장 (버퍼가 필요없음)</p>
<p>예를 들어 숫자를 입력 받아 변수에 입력하는 도중에 문자가 입력되면 해당 버퍼에 저장이 되면 버퍼에 저장된 값이 정수형 변수에 저장하려고 하기 때문에 failbit를 설정해 버퍼에 값이 계속 남고 해당 함수를 예시로 들자면 <code>===== Wrong input =====</code> 이 반복적으로 나오게 된다.</p>
<p><code>cin.clear()</code>를 통해 에러비트를 초기화하고, <code>cin.ignore()</code>를 통해 두 번째 인자인 개행으로 버퍼를 계속 비워주겠다는 뜻이다.</p>
<h3 id="contactcpp">contact.cpp</h3>
<pre><code class="language-cpp">void    Contact::Add()
{
    int    i;
    if (index == 8)
    {
        for(i = 1; i &lt; index; i++)
            book[i - 1] = book[i];
        index--;
    }
    std::cout &lt;&lt; &quot;first name : &quot;;
    std::cin &gt;&gt; book[index].first_name;
    std::cout &lt;&lt; &quot;last name : &quot;;
    std::cin &gt;&gt; book[index].last_name;
    std::cout &lt;&lt; &quot;nickname : &quot;;
    std::cin &gt;&gt; book[index].nickname;
    std::cout &lt;&lt; &quot;phone number : &quot;;
    std::cin &gt;&gt; book[index].phone_number;
    std::cout &lt;&lt; &quot;darkest secret : &quot;;
    std::cin &gt;&gt; book[index].darkest_secret;
    index++;
}</code></pre>
<p>연락처는 최대 8 개까지 저장할 수 있고, 추가로 저장을 할 때 제일 최근에 저장된 연락처가 사라진다. 연락처의 갯수가 8 개라면 반복문을 통해 해당 번호의 앞 번호로 다시 저장 후 연락처를 저장한다.</p>
<pre><code class="language-cpp">std::string    LengthCheck(std::string str)
{
    if (str.length() &gt;= 10)
    {
        str = str.substr(0, 9);
        str += &quot;.&quot;;
    }
    return (str);
}

void    Contact::Search()
{
    int    i;

    i = 0;
    std::cout &lt;&lt; &quot;|&quot;;
    std::cout &lt;&lt; std::setw(10) &lt;&lt; &quot;INDEX&quot; &lt;&lt; &quot;|&quot;;
    std::cout &lt;&lt; std::setw(10) &lt;&lt; &quot;First name&quot; &lt;&lt; &quot;|&quot;;
    std::cout &lt;&lt; std::setw(10) &lt;&lt; &quot;Last name&quot; &lt;&lt; &quot;|&quot;;
    std::cout &lt;&lt; std::setw(10) &lt;&lt; &quot;Nickname&quot; &lt;&lt; &quot;|&quot; &lt;&lt; std::endl;
    for(i = 0; i &lt; index; i++)
    {
        std::cout &lt;&lt; &quot;|&quot;;
        std::cout &lt;&lt; std::setw(10) &lt;&lt; i + 1 &lt;&lt; &quot;|&quot;;
        std::cout &lt;&lt; std::setw(10) &lt;&lt; LengthCheck(book[i].first_name) &lt;&lt; &quot;|&quot;;
        std::cout &lt;&lt; std::setw(10) &lt;&lt; LengthCheck(book[i].last_name) &lt;&lt; &quot;|&quot;;
        std::cout &lt;&lt; std::setw(10) &lt;&lt; LengthCheck(book[i].nickname) &lt;&lt; &quot;|&quot; &lt;&lt; std::endl;;
    }
    std::cout &lt;&lt; &quot;Enter the index of the name : &quot;;
    std::cin &gt;&gt; i;
    i--;
    if (index == 0)
        std::cout &lt;&lt; &quot;oh.. Phonebook is empty&quot; &lt;&lt; std::endl;
    else if (i &lt; index &amp;&amp; i &gt; 0)
    {
        std::cout &lt;&lt; &quot;Fist name      : &quot; &lt;&lt; book[i].first_name &lt;&lt; std::endl;
        std::cout &lt;&lt; &quot;Last name      : &quot; &lt;&lt; book[i].last_name &lt;&lt; std::endl;
        std::cout &lt;&lt; &quot;Nickname       : &quot; &lt;&lt; book[i].nickname &lt;&lt; std::endl;
        std::cout &lt;&lt; &quot;PhoneNumber    : &quot; &lt;&lt; book[i].phone_number &lt;&lt; std::endl;
        std::cout &lt;&lt; &quot;Darkest Secret : &quot; &lt;&lt; book[i].darkest_secret &lt;&lt; std::endl;
    }
}</code></pre>
<p>서브젝트 규정 중 연락처를 출력하는데 있어서 한정된 크기를 부여 받았고 해당 조건을 충족하기 위해 <code>setw(크기)</code>를 사용했다. 
setw()는 매개 변수만큼 공간을 잡고 그 공간에 내용을 출력한다. </p>
<p>ex) std::setw(10) &lt;&lt; “a” ⇒ <code>|         a|</code> 10칸 확보 후 “a”를 출력.</p>
<p>연락처의 내용이 10 글자 이상일 때 9개만 출력 후 <code>.</code>으로 대체하는 조건이 있었다. 
str.substr()으로 해당 문자열의 0부터 9번째의 글자만 출력하고 다음에 <code>.</code>을 출력하도록 했다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[42Seoul] CPP Module 00 - ex00]]></title>
            <link>https://velog.io/@soooh_42/42Seoul-CPP-Module-00-ex00</link>
            <guid>https://velog.io/@soooh_42/42Seoul-CPP-Module-00-ex00</guid>
            <pubDate>Thu, 30 Dec 2021 10:47:37 GMT</pubDate>
            <description><![CDATA[<h2 id="ex00-megaphone">EX00: Megaphone</h2>
<p>[<code>C++</code> 의 표준출력 <code>std::cout</code> 의 연습]</p>
<p>to_upper 프로그램 만들기</p>
<ul>
<li>제출할 디렉토리: ex00/</li>
<li>제출할 파일: Makefile, megaphone.cpp</li>
<li>금지 함수: 없음</li>
</ul>
<p>다음과 같은 동작을 하는 프로그램을 쓰세요<br><img src="https://images.velog.io/images/soooh_42/post/574cf61b-adb9-44d3-a366-782485ec07f0/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-30%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%205.47.32.png" alt=""></p>
<ul>
<li>대문자로 바꾸기</li>
<li>if (argc == 1) 출력 <code>* LOUD AND UNBEARABLE FEEDBACK NOISE *</code></li>
<li>출력시 argv 간 띄어쓰기 추가하지 않음</li>
<li>마지막줄 개행</li>
</ul>
<p>과제를 작성하기 전 C++의 표준 입출력을 알아야 한다.</p>
<h2 id="1-c-표준-입출력">1. C++ 표준 입출력</h2>
<pre><code class="language-cpp">#include &lt;iostream&gt;

int main()
{
  std::cout &lt;&lt; &quot;Hello, World!!&quot; 
    std::cout &lt;&lt; std::endl;
  return (0);
}</code></pre>
<p>C에서 사용한 <code>stdio.h</code>와 달린 C++에서는 <code>iostream</code>를 사용한다. <code>.h</code>를 안 붙인다는 차이가 있으며 함수 작성에 가장 기본적인 헤더. </p>
<p><code>iostream</code>은 C++의 입출력을 담당하는 헤더이며 객체지향언어인 C++처럼 <code>iostream</code>에 있는 입출력 함수들 역시 <strong>객체</strong>로 정의되어 있다. (<a href="https://modoocode.com/143">iostream의 구성 요소 정리</a>)</p>
<p><img src="https://images.velog.io/images/soooh_42/post/2b5a95f3-196f-480a-9e7c-e753e69b2b82/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-30%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%206.47.59.png" alt=""></p>
<aside>
💡  C++ 프로그램은 입력 시 버퍼를 만들고 Enter를 누르면 입력 버퍼를 삭제, 출력 시 개행 문자를 받으면 출력 버퍼를 지운다고 한다.

</aside>

<p><a href="https://velog.io/@hidaehyunlee/CPP-Megaphone-Warm-up-bagic-CPP">출처</a></p>
<h2 id="2-namespace">2. namespace</h2>
<p>C++ 표준 라이브러리에 존재하는 모든 변수나 객체는 std 표준 네임 스페이스에 포함된다. 표준 출력 <code>cout</code> 객체를 사용하기 위해서는 <code>std::cout</code>처럼 네임 스페이스를 붙여 사용해야 한다.</p>
<p>네임 스페이스는 정의된 객체나 함수의 소속을 의미한다. <code>a()</code>와 <code>b()</code>에 각각 <code>abc</code> 객체를 선언했을 때 <code>a::abc</code>, <code>b::abc</code>로 접두어만 다르게 해 사용할 수 있다는 뜻</p>
<pre><code class="language-cpp">int doSomething(int x, int y)
{
    return x + y;
}</code></pre>
<pre><code class="language-cpp">int doSomething(int x, int y)
{
    return x - y;
}</code></pre>
<pre><code class="language-cpp">#include &lt;iostream&gt; 
#include &quot;foo.h&quot; 
#include &quot;goo.h&quot; 
int main() 
{ 
    std::cout &lt;&lt; doSomething(4, 3);
    return 0; 
}

&gt;&gt; c:\VCProjects\goo.h(4) : error C2084: function &#39;int __cdecl doSomething(int,int)&#39; already has a body
</code></pre>
<p>예제처럼 같은 프로그램에 이 둘을 같이 포함하면 이름과 매개 변수가 같은 함수가 같은 스코프에 있음으로써 이름 충돌이 발생한다.</p>
<pre><code class="language-cpp">namespace Foo
{
    int doSomething(int x, int y)
    {
        return x + y;
    }
}</code></pre>
<pre><code class="language-cpp">namespace Goo
{
    int doSomething(int x, int y)
    {
        return x - y;
    }
}</code></pre>
<p>이제 Foo안에 <code>doSomething()</code>이, Goo안에 <code>doSomething()</code>이 있다.</p>
<p>각 네임 스페이스 안에 있는 식별자를 찾기 위해서는 <strong>스코프 분석 연산자(::)</strong>가 필요하다. 
이 연산자를 사용하려면 식별자 이름 앞에 사용할 네임 스페이스를 붙이면 된다. <code>Foo::doSomething(x, y)</code>, <code>Goo::doSomething(x, y)</code></p>
<pre><code class="language-cpp">#include &lt;iostream&gt; 

int main() 
{ 
    std::cout &lt;&lt; Foo::doSomething(4, 3); &lt;&lt; &#39;\n&#39;
    std::cout &lt;&lt; Goo::doSomething(4, 3); &lt;&lt; endl (둘 다 개행 출력임)
    return 0; 
}</code></pre>
<p><a href="https://boycoding.tistory.com/171">참고</a></p>
<h3 id="makefile">Makefile</h3>
<pre><code class="language-makefile">NAME = megaphone

CPPC = clang++
CPPFLAGS = -Wall -Wextra -Werror
RM = rm -f
MAIN = megaphone.cpp

$(NAME): $(MAIN)
    $(CPPC) $(MAIN) $(CPPFLAGS) -o $(NAME)

all : $(NAME)
clean: $(RM) $(NAME)
re:    clean all

.PHONY: all clean re</code></pre>
<p>⇒ <code>CPPC</code>, <code>CPPFLAGS</code> 매크로명은 <a href="http://doc.kldp.org/KoreanDoc/html/GNU-Make/GNU-Make-4.html">여기</a>에서 다른 의미로 쓰이는 것 같아서 다음 과제부터는 이렇게 안 써야지..</p>
<h3 id="megaphonecpp">megaphone.cpp</h3>
<pre><code class="language-cpp">#include &lt;iostream&gt;

char    CharUpper(char c)
{
    if (&#39;a&#39; &lt;= c &amp;&amp; c &lt;= &#39;z&#39;)
        return (c - (&#39;a&#39; - &#39;A&#39;));
    return (c);
}

int        main(int argc, char **argv)
{
    int        i;
    int        j;

    std::cout &lt;&lt; &quot;0&quot;;
    (void) argc;
    if (!argv[1])
        std::cout &lt;&lt; &quot;* LOUD AND UNBEARABLE FEEDBACK NOISE *&quot;;
    for (i = 1; argv[i]; i++)
    {
        for (j = 0; argv[i][j]; j++)
            std::cout &lt;&lt; CharUpper(argv[i][j]);
    }
    std::cout &lt;&lt; std::endl;
    return (0);
}</code></pre>
<p>원래 42 norminette 규정으로 for문은 사용하지 못하고 while문으로 반복문을 작성했는데 cpp는 규정이 따로 없어서 for문에 익숙해질겸 작성하였음</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[42Seoul] CPP Module]]></title>
            <link>https://velog.io/@soooh_42/42Seoul-CPP-Module</link>
            <guid>https://velog.io/@soooh_42/42Seoul-CPP-Module</guid>
            <pubDate>Thu, 30 Dec 2021 08:56:46 GMT</pubDate>
            <description><![CDATA[<p>네임 스페이스, 클래스, 멤버 함수, stdio 스트림, 초기화 목록, 정적, 상수 등등에 대해 공부합니다</p>
<p>C++ Module에서는 C++98만 사용하고 있습니다.
객체 지향 프로그래밍의 기초를 공부하는 것을 목표로 합니다.
현재의 C++와 42에서 공부할 C++가 많은 면에서 다르다는 것을 알고 있다.
숙련된 C++ 코더가 되고 싶다면 현대적인 표준 C++이 필요할 것이다.</p>
<h2 id="general-rules">General rules</h2>
<ul>
<li>Header 안에 구현된 모든 기능 및 보호되지 않은 Header는 0 점을 의미합니다</li>
<li>모든 출력은 표준 출력이며, 기본적으로 개행으로 끝납니다.</li>
<li>파일 이름에는 <strong><em>letter, class name, function name, method name</em></strong>이 와야 합니다.</li>
<li>명심하세요. 당신은 이제 C가 아닌 C++로 코딩하고 있습니다.<ul>
<li>다음 기능은 금지된 기능입니다. 해당 기능을 사용하면 0 점 처리를 받습니다. <strong><em>*alloc, *printf, free</em></strong></li>
<li>표준 라이브러리의 모든 것을 사용할 수 있습니다. C++ 버전의 함수를 사용하는 것이 현명할 것입니다.(C++은 새로운 언어이니까요)</li>
<li>CPP Module08까지 <a href="https://boycoding.tistory.com/124">STL</a>은 사용할 수 없습니다. include를 필요로 하는 <strong><em>vectors, lists, maps</em></strong> 등등</li>
</ul>
</li>
<li>명시적으로 금지된 기능이나 기계의 사용은 바로 0 점 처리를 받습니다</li>
<li>또한 명시되지 않은 한 C++ 키워드 <strong><em>using namespace</em></strong>및 <strong><em>friend</em></strong>는 금지되어 있습니다.<ul>
<li>사용시 -42 점을 받을 것입니다.</li>
</ul>
</li>
<li>클래스와 관련된 파일은 별도로 지정되지 않는 한 항상 <strong><em>ClassName.hpp</em></strong> 및 <strong><em>ClassName.cpp</em></strong>입니다.</li>
<li>반환 디렉토리는 ex00, ex01, ... , exn입니다.</li>
<li>예제를 꼼꼼히 읽어야 합니다. 각 문제의 설명에서는 명확하지 않았던 요구 사항을 포함할 수 있습니다.</li>
<li>앞에서 배운 C++도구는 사용할 수 있으므로 외부 라이브러리는 사용할 수 없습니다.<ul>
<li>C++11과 파생 모델, Boost 또는 C++이 없다면 활용하지 못하는 기술들도 포함입니다 == for문</li>
</ul>
</li>
<li>상당한 양의 Class를 제출해야 할 수도 있습니다. 이것을 텍스트 편집기로 스크립팅할 수 없는 경우 지루해 보일 수 있습니다.</li>
<li>각 문제를 시작하기 전에 완벽히 이해하셔야 해요!</li>
<li>사용할 컴파일러는 <strong>clang++</strong>입니다.</li>
<li>코드는 다음 플래그를 사용하여 컴파일해야합니다: <strong>Wall -Wextra -Werror</strong></li>
<li>당신의 각 includes는 다른 includes들과 독립적으로 포함될 수 있어야 합니다. Includes는 분명히 그들이 의존하는 다른 모든 include를 포함해야합니다.</li>
<li>C++에서는 norminette가 적용되지 않습니다. 원하는 스타일대로 작성해 보세요. 하지만 동료 평가자가 읽을 수 없는 코드는 채점 받을 수 없겠죠.</li>
<li>중요한 사항 - 서브젝트에 명시되지 않은 한 프로그램에 의해 채점되지 않습니다. 과제를 선택하는 자유가 주어집니다. 하지만 제약에 유의하고 게으름을 피우지 마세요. 연습이 제공하는 많은 것을 놓칠 수 있습니다.</li>
<li>제출하는 파일에 일부 관계없는 파일이 있는 것은 문제가 되지 않습니다. 요청한 파일보다 더 많은 파일에 코드를 분리할 수 있습니다. 프로그램에 의해 채점되지 않는 한 자유롭게 하실 수 있습니다.</li>
<li>비록 서브젝트의 문제가 짧더라도 알아야 할 것을 확실히 이해하고, 최선의 방법으로 풀었다는 것을 증명하기 위해 시간을 할애할 가치가 있습니다</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[42_JAVA Study 06]]></title>
            <link>https://velog.io/@soooh_42/42JAVA-Study-06</link>
            <guid>https://velog.io/@soooh_42/42JAVA-Study-06</guid>
            <pubDate>Fri, 10 Dec 2021 06:59:46 GMT</pubDate>
            <description><![CDATA[<h1 id="6주차-서브젝트">6주차 서브젝트</h1>
<h2 id="1-인터페이스">1. 인터페이스</h2>
<p><code>#인터페이스</code> <code>#인터페이스구현</code> <code>#인터페이스란무엇인가?</code> <code>#인터페이스에선언된변수는?</code> <code>#인터페이스와다형성</code> </p>
<h2 id="2-인터페이스의-여러-요소들">2. 인터페이스의 여러 요소들</h2>
<p><code>#상수</code> <code>#디폴트메서드</code> <code>#디폴트메서드 재정의 하기</code> <code>#static메서드</code> <code>#private메서드</code></p>
<h2 id="인터페이스">인터페이스</h2>
<p>동일한 목적 하에 동일한 기능을 수행하게 강제하는 것이 인터페이스의 역할이자 개념
자바의 다형성을 극대화하여 개발 코드 수정을 줄이고 프로그램 유지보수성을 높이기 위해 인터페이스를 사용한다</p>
<p>인터페이스는 <code>interface</code> 키워드를 통해 선언할 수 있으며 <code>implements</code> 키워드를 통해 일반 클래스에서 인터페이스를 구현할 수 있다</p>
<aside>
💡 또한, JAVA8 이전까지는 상수, 추상 메소드만 선언이 가능하지만 (상수, 추상 메소드만 가능하게 했다는 것을 통해 그만큼 강제성이 강했다는 것을 유추할 수 있다) JAVA8부터 디폴트메소드, 정적 메소드가 추가되었다 (디폴트메소드, 정적 메소드를 통해, 구현 강제성 안에 유연함을 심었다고 우선 이해하자)

</aside>

<pre><code class="language-java">public interface 인터페이스명 {
        //상수        
        타입 상수명 = 값; -&gt; 인터페이서에서 값을 지정. 바꾸지 말고 제공한 값만 참고할 것 (절대적)

        //추상 메소드            
        타입 메소드명(매개변수, ... ); -&gt; 가이드만 준다. 추상 메소드를 오버라이팅해서 재구현할 것 (강제적)

        //디폴트 메소드            
        default 타입 메소드명(매개변수, ... ){    -&gt; 인터페이스에서 기본적으로 제공. 수정 가능 (선택적)
          //구현부
        } 

        //정적 메소드            
        static 타입 메소드명(매개변수) {    -&gt; 인터페이스에서 제공해 주는 것으로 무조건 사용해야 함 (절대적)    
          //구현부            
        }
}</code></pre>
<p>절대적 - 변경하면 안 된다
강제적 - 인터페이스를 <code>implements</code>하지 않으면 피할수는 있기에 강제적이라 표현</p>
<h2 id="특징">특징</h2>
<ul>
<li>class 가 아닌 interace 키워드 사용<ul>
<li>파일도 class가 아닌 interface로 생성 가능</li>
<li>public과 default 접근제어자 사용 가능<ul>
<li>클래스와 비슷한 속성</li>
</ul>
</li>
</ul>
</li>
<li>멤버 변수는 항상 public static final 이다<ul>
<li>인터페이스에는 클래스 멤버 변수밖에 생성하지 못한다</li>
<li>인터페이스는 객체를 생성하지 않기 때문에 객체 멤버 변수가 없다<ul>
<li>객체를 생성하지 않기 때문에 생성자도 없다</li>
</ul>
</li>
<li>public static final 키워드는 생략 가능</li>
</ul>
</li>
<li>멤버 메소드는 항상 public abstract 이다<ul>
<li>정의상으로 모든 메서드가 추상 메소드인 클래스이기 때문에 당연함</li>
<li>오버라이딩을 위한 메서드이기 때문에 private 메소드는 의미가 없다</li>
<li>public abstract는 생략 가능하다</li>
</ul>
</li>
<li>정적 메소드도 선언 가능하다<ul>
<li>정적 메소드는 추상 메소드가 될 수 없다<ul>
<li>정적 메소드는 구현부가 있어야 한다</li>
</ul>
</li>
<li>정적 메소드는 오버라이딩할 수 없다</li>
</ul>
</li>
<li>인터페이스의 상속은 implements 키워드를 사용한다</li>
<li>클래스는 하나만 상속할 수 있으나 인터페이스는 여러 개를 구현 가능<ul>
<li>extends 하고 하나의 클래스만 적을 수 있지만, 인터페이스는 implements하고 여러 클래스를 적을 수 있다<ul>
<li>이때 구현한 인터페이스들의 메소들을 구현 받은 클래스에서 모두 구현해야 함</li>
</ul>
</li>
<li>이를 통해 다중 상속처럼 사용할 수 있다<ul>
<li>TVCR예제</li>
</ul>
</li>
</ul>
</li>
<li>인터페이스명을 자료형으로 하여 구현체의 객체를 참조할 수 있다<ul>
<li>상속 관계의 경우와는 다르게 인터페이스의 객체는 생성되지 않는다</li>
<li>그러나 메소드는 오버라이딩하기 때문에 가상 메소드 호출은 일어난다</li>
<li>이를 통해 다형성을 구현할 수 있다</li>
</ul>
</li>
<li>추상 메소드가 없다면 구현체에서 메소드 구현을 안 해도 된다</li>
<li>인터페이스는 객체를 생성할 수 없다</li>
</ul>
<pre><code class="language-java">interface IFoo{
    public static final int MEMBER_VAR = 10; // (상수는 대문자와 &#39;_&#39;조합)
                                            // public static final 생략 가능

    public abstract void methodA(int param); // public abstract 생략가능
    void methodB(int param); // public abstract
}

class Foo implements IFoo{

    @Override
    public void methodA(int param) {
        System.out.println(param);
    }

    @Override
    public void methodB(int param) {
        System.out.println(param);
    }
}</code></pre>
<ul>
<li>인터페이스의 이름 예시<ul>
<li>1) interface ifoo &lt; class Foo<ul>
<li>상속하는 자식에서 부모쪽으로 화살표한다</li>
</ul>
</li>
<li>2) interface Printable ← class Bar</li>
<li>1)과 같이 인터페이스명에 대문자 I를 붙여서 구분한다<ul>
<li>혹은 2)와 같이 형용사로 표현하기 좋은 이름은 그냥 제목으로 표현</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>썸네일: <a href="https://velog.io/@oneook/%EC%8D%B8%EB%84%A4%EC%9D%BC-%EB%A9%94%EC%9D%B4%EC%BB%A4Thumbnail-Maker-Toy-Project">oneook</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[42_JAVA Study 05 ]]></title>
            <link>https://velog.io/@soooh_42/42JAVA-Study-05</link>
            <guid>https://velog.io/@soooh_42/42JAVA-Study-05</guid>
            <pubDate>Fri, 10 Dec 2021 06:58:45 GMT</pubDate>
            <description><![CDATA[<h1 id="5주차-서브젝트">5주차 서브젝트</h1>
<h2 id="1-추상클래스">1. 추상클래스</h2>
<p><code>#추상메서드(abstract method)</code> <code>#추상클래스(abstract class)</code>  <code>#추상클래스를 사용하는 이유?</code> <code>#훅(Hook)메서드</code> <code>#추상 클래스와 템플릿 메서드 패턴</code> <code>#final 예약어는 언제 사용하는가?</code></p>
<h2 id="추상메서드">추상메서드</h2>
<p>자식 클래스에서 반드시 오버라이딩 해야 사용할 수 있는 메소드를 의미
선언부만 존재하며 구현부는 작성되지 않는다 → 작성되지 않은 구현부를 자식클래스에서 오버라이딩하여 사용</p>
<p>→ 추상 메소드가 포함된 클래스를 상속받는 자식 클래스가 반드시 추상 메소드를 구현하도록 하기 위함</p>
<p>ex) 모듈처럼 중복되는 부분이나 공통적인 부분은 미리 다 만들어진 것을 사용하고, 이를 받아 사용하는 쪽에서 자신에게 필요한 부분만 재정의해 사용함으로 생상성 향상과 배포 용이</p>
<pre><code class="language-java">abstract 반환타입 메소드이름();</code></pre>
<p>선언부만 있고 구현부가 없다는 의미로 선언부 끝에 바로 세미콜론(;) 추가</p>
<h2 id="추상클래스">추상클래스</h2>
<p>하나 이상의 추상 메소드를 포함하는 클래스를 가리켜 추상 클래스라고 한다
추상 클래스는 객체 지향 프로그래밍에서 중요한 특징인 다형성을 가지는 메소드의 집합을 정의할 수 있도록 함
즉, 반드시 사용되어야 하는 메소드를 추상클래스에 추상메소드로 선언해 놓으면 이 클래스를 상속받는 모든 클래스에서는 이 추상메소드를 반드시 재정의해야 한다</p>
<pre><code class="language-java">abstract class 클래스이름 {
    ...
    abstract 반환타입 메소드이름();
    ...
}</code></pre>
<p>추상 클래스는 동작이 정의되어 있지 않은 추상 메소드를 포함하고 있으므로, 인스턴스를 생성할 수 없다
추상 클래스는 먼저 상속을 통해 자식 클래스를 만들고, 만든 자식 클래스에서 추상 클래스의 모든 추상 메소드를 오버라이딩하고 나서야 비로소 자식 클래스의 인스턴스를 생성할 수 있다</p>
<aside>
☝ 추상 클래스는 추상 메소드를 포함하고 있다는 점을 제외하면, 일반 클래스와 모든 점이 같습니다.

<p>즉, 생성자와 필드, 일반 메소드도 포함할 수 있습니다.</p>
</aside>

<h2 id="추상클래스를-사용하는-이유">추상클래스를 사용하는 이유</h2>
<p>자식 클래스에서 추상메소드를 반드시 구현하도록 강요하기 위해서 
상속받은 자식 클래스에서는 메소드들이 완전히 구현된 것으로 인식하고 오버라이딩하지 않을 수 있기 때문이다
(추상 클래스로 객체를 생성하려면 자식 클래스를 작성해야 하며 추상메소드들을 오버라이딩해야 한다)
이는 추상 클래스를 사용해 유지보수의 편의성을 높이기 위함이고 최소한의 수정으로 원하는 객체를 사용할 수 있게 되어 유지보수성이 좋아진다</p>
<h2 id="템플릿-메서드-패턴">템플릿 메서드 패턴</h2>
<p>어떤 작업을 처리하는 일부분을 서브 클래스로 캡슐화해 전체 일을 수행하는 구조는 바꾸지 않으면서 특정 단계에서 수행하는 내역을 바꾸는 패턴</p>
<ul>
<li>전체적으로 동일하면서 부분적으로 다른 구문으로 구성된 메서드의 코드 중복을 최소화할 때 유용</li>
<li>다른 관점에서 보면 동일한 기능을 상위 클래스에서 정의하면서 확장/변화가 필요한 부분만 서브 클래스에서 구현할 수 있도록 한다</li>
<li>예를 들어 전체적인 알고리즘은 상위 클래스에서 구현하면서 다른 부분은 하위 클래스에 구현할 수 있도록 함으로써 전체적인 알고리즘 코드를 재사용하는 데 유용</li>
</ul>
<p>-장점</p>
<p>코드 중복 감소</p>
<p>자식 클래스의 영할을 감소시키면서 핵심 로직 관리 용이</p>
<p>객체 추가 및 확장 쉽게 가능</p>
<p>-단점</p>
<p>추상메소드가 많아지면 클래스 관리가 복잡</p>
<p>추삭클래스와 구현클래스간 복잡성 증대</p>
<h3 id="구조-설명">구조 설명</h3>
<p><img src="https://images.velog.io/images/soooh_42/post/86368c69-4ee0-4319-a3ad-d99c85cbcb2b/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-10%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.58.22.png" alt=""></p>
<p>AbstractClass</p>
<ul>
<li>템플릿 메서드를 정의하는 클래스</li>
<li>하위 클래스에 공통 알고리즘을 정의하고 하위 클래스에서 구현될 기능을 primitive메서드 또는 hook메서드로 정의하는 클래스</li>
</ul>
<p>ConcreteClass </p>
<ul>
<li>물려받은 primitive메서드 또는 hook메서드를 구현하는 클래스</li>
<li>상위 클래스에 구현된 템플릿 메서드의 일반적인 알고리즘에서 하위 클래스에 적합하게 primitive메서드나 hook메서드를 오버라이드하는 클래스</li>
</ul>
<blockquote>
<p>hook메서드</p>
</blockquote>
<ul>
<li>선택적으로 오버라이딩할 수 있는 메서드<blockquote>
</blockquote>
</li>
</ul>
<h2 id="final-예약어는-언제-사용하는가">final 예약어는 언제 사용하는가?</h2>
<p>위키백과에서 설명하는 final (Java) 정의와 예제는 다음과 같다.</p>
<blockquote>
<p>the final keyword is used in several contexts to define an entity that can only be assigned once.</p>
</blockquote>
<p>final 키워드는 엔티티를 한 번만 할당합니다. 즉, 두 번 이상 할당하려 할 때 컴파일 오류가 발생하여 확인이 가능합니다.</p>
<aside>
☝ Java에서의 final은 Immutable/Read-only 속성을 선언하는 지시어입니다.
**클래스, 함수, 변수가 변하지 못하도록 의도하고 싶다면 final로 선언하자.**

</aside>

<p>썸네일: <a href="https://velog.io/@oneook/%EC%8D%B8%EB%84%A4%EC%9D%BC-%EB%A9%94%EC%9D%B4%EC%BB%A4Thumbnail-Maker-Toy-Project">oneook</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[42_JAVA Study 04 - 오버라이딩]]></title>
            <link>https://velog.io/@soooh_42/42JAVA-Study-04-%EC%98%A4%EB%B2%84%EB%9D%BC%EC%9D%B4%EB%94%A9</link>
            <guid>https://velog.io/@soooh_42/42JAVA-Study-04-%EC%98%A4%EB%B2%84%EB%9D%BC%EC%9D%B4%EB%94%A9</guid>
            <pubDate>Fri, 10 Dec 2021 06:56:53 GMT</pubDate>
            <description><![CDATA[<h2 id="메소드-오버라이딩method-overriding">메소드 오버라이딩(method overriding)</h2>
<p>앞서 공부한 <strong><a href="https://www.notion.so/Week01-f4d37f3877f548a4bef90e4dd152aa9d">오버로딩</a></strong>은 서로 다른 시그니처를 갖는 여러 메소드를 하나의 이름으로 정의하는 것</p>
<p><strong>오버라이딩은</strong> <a href="https://www.notion.so/f17c9819ad39474a813eb56df37e80f3">상속</a> 관계에 있는 부모 클래스에서 이미 정의된 메소드를 자식 클래스에서 같은 시그니처를 갖는 메소드로 다시 정의하는 것</p>
<h2 id="오버라이딩-조건">오버라이딩 조건</h2>
<ol>
<li>메소드의 동작만을 재정의 하기 때문에 메소드의 선언부는 기존 메소드와 완전이 같아야 함
하지만 메소드의 반환 타입은 부모 클래스의 반환 타입이기 떄문에 타입 변환할 수 있는 타입이라면 변경 가능</li>
<li>부모 클래스의 메소드보다 접근 제어자를 더 좁은 범위로 변경할 수 없다</li>
<li>부모 클래스의 메소드보다 더 큰 범위의 예외를 선언할 수 없다</li>
</ol>
<pre><code class="language-java">class Parent {
    void display() { System.out.println(&quot;부모 클래스의 display() 메소드입니다.&quot;); }
}
class Child extends Parent {
    void display() { System.out.println(&quot;자식 클래스의 display() 메소드입니다.&quot;); }
}

public class Inheritance05 {
    public static void main(String[] args) {
        Parent pa = new Parent();
        pa.display();
        Child ch = new Child();
        ch.display();
        Parent pc = new Child();
        pc.display(); // Child cp = new Parent();
    }
}

&gt;&gt; 실행 결과

부모 클래스의 display() 메소드입니다.
자식 클래스의 display() 메소드입니다.
자식 클래스의 display() 메소드입니다.</code></pre>
<p><code>// Child cp = new Parent();</code></p>
<p>예제에서 세 번째와 같은 인스턴스의 참조가 허용되는 이유는 자바에서의 다형성(polymorphism)때문</p>
<p><a href="https://www.notion.so/polymorphism-b3b6d2277bec4d3c9b90416641c31745">다형성(polymorphism)</a></p>
<hr>
<h2 id="오버로딩과-오버라이딩">오버로딩과 오버라이딩</h2>
<blockquote>
<p>오버로딩 - 새로운 메소드 정의
오버라이딩 - 상속받은 기존의 메소드 재정의</p>
</blockquote>
<p>밑의 예제는 오버로딩과 오버라이딩 둘 다 수행하는 예제</p>
<pre><code class="language-java">class Parent {
    void display() { System.out.println(&quot;부모 클래스의 display() 메소드입니다.&quot;); }
}

class Child extends Parent {
    // 오버라이딩된 display() 메소드
    void display() { System.out.println(&quot;자식 클래스의 display() 메소드입니다.&quot;); }
    void display(String str) { System.out.println(str); } // 오버로딩된 display() 메소드
}

public class Inheritance06 {
    public static void main(String[] args) {
        Child ch = new Child();
        ch.display();
        ch.display(&quot;오버로딩된 display() 메소드입니다.&quot;);
    }
}

&gt;&gt; 실행 결과
자식 클래스의 display() 메소드입니다.
오버로딩된 display() 메소드입니다.</code></pre>
<h2 id="형변환">형변환</h2>
<h3 id="암묵적-형변환">암묵적 형변환</h3>
<p>서로 다른 자료형을 연산 혹은 대입하는 경우 자바 컴파일러가 자료형을 통일</p>
<p>→ 표현 범위가 좁은 데이터 타입에서 넓은 데이터 타입으로의 변환만 허용 (데이터 손실이 되기 때문)
<img src="https://images.velog.io/images/soooh_42/post/7a4b704b-0ddf-4f38-898f-3cf1454b9bf4/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-10%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.55.48.png" alt=""></p>
<h3 id="명시적-형변환">명시적 형변환</h3>
<p>데이터 손실을 감수하더라도 강제로 형변환 시키는 형태</p>
<p>→ <code>자료형 b = (변화할 자료형) a;</code> (실수형에서 정수형으로 변환하는 경우 소수점 이하 자리는 버려짐)</p>
<pre><code class="language-java">public class Main01 {
    public static void main(String[] args) {
        double a = 3.14d;
        int b = (int) a;

        System.out.println(a);
        System.out.println(b);
    }
}

&gt;&gt; 실행 결과
3.14
3</code></pre>
<h2 id="가상-메서드">가상 메서드</h2>
<p>함수 혹은 메서드는 이름이 그 자체로 주소 역할을 하기 때문에 같은 이름을 가진 다른 메서드가 존재할 수 없지만 오버라이드를 하는 경우 같은 이름의 다른 주소값을 가진 메서드가 재정의 되기 때문에 같은 이름의 다른 기능을 하는 메서드를 가질 수 있다</p>
<p>오버라이드를 할 수 있는 메서드 = 가상 메서</p>
<p><img src="https://images.velog.io/images/soooh_42/post/dfc1a656-da01-4137-8b7d-1f71744bb782/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-10%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.56.13.png" alt=""></p>
<p>calcPrice는 이름이 같지만 재정의된 다름함수가 존재하고 그 주소값이 다르다. 이럴 때 실제적으로 호출되는 calPrice는 자료형(타입)기준이 아닌 생성된 인스턴스를 기준으로 호출이 되는 것을 가상 메서드 기법이라고 한다</p>
<p>정리해보면 Customer vd = new VIPCustomer(); 일 때 재정의가 안됬을 경우 Customer의 calPrice가 호출되지만 재정의가 됬을 경우 VIPCustoemr의 calPrice가 호출</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[42_JAVA Study 04 - 상속]]></title>
            <link>https://velog.io/@soooh_42/42JAVA-Study-04-%EC%83%81%EC%86%8D</link>
            <guid>https://velog.io/@soooh_42/42JAVA-Study-04-%EC%83%81%EC%86%8D</guid>
            <pubDate>Fri, 10 Dec 2021 06:54:20 GMT</pubDate>
            <description><![CDATA[<h2 id="상속inheritance">상속(Inheritance)</h2>
<p>일반적인 상속의 개념처럼 부모 → 자식 에게 받는 것이 아닌 자식 → 부모를 선택해 상속 받는다.</p>
<p>상속받은 클래스 = 자식 클래스, 하위 클래스, 서브 클래스 라고 부른다
상속해 준 클래스 = 부모 클래스, 상위 클래스, 슈퍼 클래스</p>
<h3 id="상속의-대상">상속의 대상</h3>
<p>자식 클래스가 상속을 받게 되면 부모 클래스의 필드와 메소드를 받는다. 
단, <code>private</code>를 갖는 필드나 메소드는 상속이 불가하고, 패키지가 다른 경우 <code>default</code>인 경우에도 상속이 불가</p>
<h3 id="상속의-방법선언">상속의 방법(선언)</h3>
<p>상속받을 자식 클래스 뒤에 <code>extends</code> 키워드를 사용하고 부모 클래스를 적으면 된다</p>
<pre><code class="language-java">class /*자식 클래스*/ extends /*부모 클래스*/{
    ..
}</code></pre>
<p>자바에서는 자식 클래스가 여러 부모로부터 다중 상속을 받는 것은 불가능하다.
1 개의 부모 클래스로부터 단일 상속만 허용된다. 하지만 여러 개의 자식 클래스에게 상속이 가능</p>
<p><img src="https://images.velog.io/images/soooh_42/post/403b2c0e-d554-43ab-9153-b511872ca201/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-10%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.42.52.png" alt=""></p>
<h2 id="상속의-사용-예제">상속의 사용 (예제)</h2>
<ul>
<li>예제1</li>
</ul>
<pre><code class="language-java">class A {
    String aField = &quot;클래스 A 필드&quot;;
    public void aMethod() {
        System.out.println(aField);
    // System.out.println(&quot;A : &quot;+ bField); 
        // 컴파일 에러(자식 필드 사용 불가)
    }
}</code></pre>
<pre><code class="language-java">
class B extends A {
    String bField = &quot;클래스 B 필드&quot;;
    public void bMethod() {
        System.out.println(aField); // 부모 클래스 필드 사용
        System.out.println(bField); // 본인 클래스 필드 사용
    // System.out.println(&quot;B : &quot;+cField); 
    // 컴파일 에러(자식 필드 사용 불가)
    }
}</code></pre>
<pre><code class="language-java">class C extends B {
    String cField = &quot;클래스 C 필드&quot;;
    public void cMethod() {
        System.out.println(aField); // 조부모 클래스 필드 사용
        System.out.println(bField); // 부모 클래스 필드 사용
        System.out.println(cField); // 본인 클래스 필드 사용
    }
}</code></pre>
<pre><code class="language-java">public class SuperSubEx01 {
    public static void main(String[] args) {
        System.out.println(&quot;----------A----------&quot;);
        A a = new A();
        a.aMethod(); // 본인 메소드 사용
        // a.bMethod(); // A(부모) 객체로 B(자식) 메소드 접근 불가
        System.out.println(&quot;----------A----------&quot;);
        System.out.println(&quot;----------B----------&quot;);
        B b = new B();
        b.aMethod(); // 부모 메소드 사용
        b.bMethod(); // 본인 메소드 사용
        // b.cMethod(); // B(부모) 객체로 C(자식) 메소드 접근 불가
        System.out.println(&quot;----------B----------&quot;);
        System.out.println(&quot;----------C----------&quot;);
        C c = new C();
        c.aMethod(); // 조부모 메소드 사용
        c.bMethod(); // 부모 메소드 사용
        c.cMethod(); // 본인 메소드 사용
        System.out.println(&quot;----------C----------&quot;);
    }
}</code></pre>
<p>A, B, C를 각각 정의하고 A(조부모)→B(부모)→C(자식) 순으로 상속을 받는다. 
각 메소드에서 부모 클래스의 필드를 자식 클래스가 사용하여 데이터를 출력한다</p>
<p>main에서 각 클래스 별로 인스턴스를 생성하고 자식 클래스에서 부모 클래스의 메소드를 호출한다</p>
<ul>
<li>예제2</li>
</ul>
<pre><code class="language-java">import java.util.Scanner;
class SuperClass {
    int a, b; // 필드
    public void setA(int a) {
        this.a = a; // 필드 a값 설정
    }
    public void setB(int b) {
        this.b = b; // 필드 b값 설정
    }
    public void sum() {
        System.out.println(&quot;덧셈 : &quot; + (a + b));
    }
    public void substract() {
        System.out.println(&quot;뺄셈 : &quot; + (a - b));
    }
}

class SubClass extends SuperClass {
    public void mul() {
        System.out.println(&quot;곱셈 : &quot; + a * b);
    }
    public void div() {
        System.out.println(&quot;나눗셈 : &quot; + a / b);
    }
}

public class SuperSubEx02 {
    public static void main(String[] args) {
        System.out.println(&quot;2개의 정수 입력&quot;);
        Scanner sc = new Scanner(System.in);
        int a = sc.nextInt();
        int b = sc.nextInt();
        SubClass sub = new SubClass();
        sub.setA(a); // 매개값 전달
        sub.setB(b); // 매개값 전달
        sub.sum();
        sub.substract();
        sub.mul();
        sub.div();
      }
}</code></pre>
<p>자식 클래스에서 부모 클래스의 기능을 물려받고 필요한 기능을 추가한 예제. 
자식 클래스가 부모 클래스보다 더 다양한 기능을 수행할 수 있다.</p>
<p>main에서 서브 클래스로 인스턴스를 생성</p>
<aside>
💡 요약

<ol>
<li><code>class /*자식 클래스*/ extends /*부모 클래스*/{ .. }</code><ol start="2">
<li>자식은 부모로부터 메소드와 필드를 물려받는다. 
2-1. 부모는 자식에서 정의한 메소드나 필드를 사용하지 못한다 (<code>자식 = 자신 + 부모 / 부모 = 자신</code>)</li>
<li>자식은 하나의 부모에게만 상속 받을 수 있다. <code>단일 상속</code>만 가능하다.</li>
<li>부모는 여러 자식에게 상속이 가능하다</li>
<li>자식 클래스가 더 다양한 기능이 가능하기 때문에 <code>자식 클래스로 인스턴스를 생성하는 것이 효율적</code></li>
</ol>
</li>
</ol>
</aside>

<p><a href="https://www.notion.so/super-super-e5486fb465e144f38cc3ce6b00b4b080">super와 super()</a></p>
<ul>
<li><p>protected</p>
<p>  <code>protected</code>는 <code>pubic</code>과 <code>default</code>접근 제한의 중간에 해당한다.</p>
<p>  같은 패키지에서는 default와 같이 접근 제한은 없지만 다른 패키지에서는 자식 클래스만 접근을 허용한다
  <img src="https://images.velog.io/images/soooh_42/post/704d9147-cbc5-41d6-a249-20600ddfa9b1/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-10%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.43.20.png" alt=""></p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[42_JAVA Study 04]]></title>
            <link>https://velog.io/@soooh_42/42JAVA-Study-04</link>
            <guid>https://velog.io/@soooh_42/42JAVA-Study-04</guid>
            <pubDate>Fri, 10 Dec 2021 06:53:17 GMT</pubDate>
            <description><![CDATA[<h1 id="4주차-서브젝트">4주차 서브젝트</h1>
<h3 id="1-상속">1. <a href="https://www.notion.so/Week04-8ce8cd81737449ebad0d8e12eaef04ec">상속</a></h3>
<p><code>#[상속]</code> <code>#하위클래스의생성순서</code> <code>#상위클래스생성자호출</code> <code>#[super]</code> <code>#[protected]</code></p>
<h3 id="2-오버라이딩">2. 오버라이딩</h3>
<p><code>#[overriding]</code> <code>#업캐스팅(upcasting)</code> <code>#[묵시적형변환]</code> <code>#상속에서의상위클래스와하위클래스의메모리상태</code> <code>#가상메서드</code> <code>#[다형성]</code></p>
<h3 id="3-다운캐스팅">3. 다운캐스팅</h3>
<p><code>#다운캐스팅</code> <code>#instanceof</code> <code>#명시적형변환</code></p>
<h3 id="q-상속을-언제-사용할-것인가">Q. 상속을 언제 사용할 것인가?</h3>
<h3 id="q-상속이-코드의-재사용을-위한-일반적인-방법이-아니라고-하면-코드를-재사용하기-위한-방법은-무엇이-있을까">Q. 상속이 코드의 재사용을 위한 일반적인 방법이 아니라고 하면 코드를 재사용하기 위한 방법은 무엇이 있을까?</h3>
<h3 id="q-is-a-와-has-a-관계">Q. IS-A 와 HAS-A 관계</h3>
<ul>
<li><p>A</p>
<h3 id="is-a관계is-a-relationship--inheritance">IS-A관계(is a relationship : inheritance)</h3>
<ul>
<li><p>IS - A관계는 일반적인(general)개념과 구체적인(specific)개념과의 관계를 뜻합니다. 한 클래스와 다른 클래스가 IS-A관계 일 때 상속을 사용합니다.</p>
</li>
<li><p>상위 클래스는 일반적인 개념 클래스이고(예 포유류) 하위 클래스는 구체적인 개념 클래스(예: 사람, 원숭이, 고래..)에 속합니다.</p>
</li>
<li><p>클래스간에 상속관계가 만들어지면 클래스간에 관계가 타이트해져서 상위 클래스에 변화를 주면 하위클래스에 영향을 주게 됩니다. 그렇기에 단순히 코드를 재사용하는 목적으로 상속을 사용하지는 않습니다.</p>
<h3 id="has-a관계composition">HAS-A관계(composition):</h3>
</li>
<li><p>반면에 HAS-A관계는 한 클래스가 다른 클래스를 소유한 관계로 코드 재사용의 한 방법입니다.</p>
</li>
<li><p>만약 우리가 ArrayList클래스를 사용하고 싶다면 ArrayList extends하여 사용 하는 것이 아닌 인스턴스를 하나 생성해서 사용하는 것 같이 필요한 코드를 재사용을 위해선 생성해서 사용하면 됩니다.</p>
</li>
</ul>
</li>
</ul>
<h3 id="q-하위-클래스가-상위-클래스-형으로-묵시적-형변환이-되는-이유를-메모리로-설명하세요">Q. 하위 클래스가 상위 클래스 형으로 묵시적 형변환이 되는 이유를 메모리로 설명하세요</h3>
<p>썸네일: <a href="https://velog.io/@oneook/%EC%8D%B8%EB%84%A4%EC%9D%BC-%EB%A9%94%EC%9D%B4%EC%BB%A4Thumbnail-Maker-Toy-Project">oneook</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[42_JAVA Study 03]]></title>
            <link>https://velog.io/@soooh_42/42JAVA-Study-03</link>
            <guid>https://velog.io/@soooh_42/42JAVA-Study-03</guid>
            <pubDate>Fri, 10 Dec 2021 06:40:14 GMT</pubDate>
            <description><![CDATA[<h1 id="3주차-서브젝트">3주차 서브젝트</h1>
<h3 id="1-static-변수">1. static 변수</h3>
<p><code>#static변수</code> <code>#static 메서드</code> <code>#클래스변수</code> <code>#클래스 메서드</code> <code>#static 생성 시기</code></p>
<ul>
<li>학생이 한 명 생성될 때 id가 새로 만들어져야 한다 -&gt; 인스턴스가 공통으로 사용할 변수가 있어야 한다 == static 변수</li>
</ul>
<h3 id="2-singleton-pattern">2. singleton pattern</h3>
<p><code>#singleton pattern</code> <code>#객체의 유일성</code></p>
<ul>
<li>디자인 패턴에 대해 일찍 공부할 필요는 없지만 알아두면 좋다 &#39;oop코딩&#39;을 조금 해 보면 된다</li>
<li>글로벌 변수는 프로그래밍의 악</li>
</ul>
<h3 id="3-변수의-종류와-유효성">3. 변수의 종류와 유효성</h3>
<p><code>#지역 변수</code> <code>#인스턴스 변수</code> <code>#static 변수의 scope와 life cycle</code> <code>생성되는 메모리</code> <code>#언제 소멸되는지</code></p>
<ul>
<li>코드 영역과 데이터 영역 중 데이터 영역에 어떤 값이 쓰이는지 (상수, 리터럴 등) 같이 공부할 수 있음</li>
</ul>
<h3 id="4-객체-배열">4. 객체 배열</h3>
<p><code>#객체배열사용하기</code> <code>#얕은복사, 깊은복사</code></p>
<ul>
<li>프리미티브 변수 X</li>
<li>배열 복사한 경우에 기존 배열과 복사한 배열의 내용이 같이 변한다</li>
</ul>
<h3 id="5-arraylist">5. ArrayList</h3>
<p><code>#ArrayList 클래스 메서드</code> <code>#javaDoc #enhanced for문</code></p>
<ul>
<li>jdk에서 제공하는 객체 배열을 위한 클래스</li>
</ul>
<hr>
<h2 id="static">Static</h2>
<p>static 변수와 static 메소드는 static 메모리 영역에 존재하기 때문에 객체가 생성되기 이전에 이미 할당되어 있다 -&gt; 객체의 생성 없이 바로 접근할 수 있다</p>
<pre><code class="language-java">public class MyCalculator {
  public static String appName = &quot;MyCalculator&quot;;
    public static int add(int x, int y) {
        return x + y;
    }
    public int min(int x, int y) {
        return x - y;
    }
}

MyCalculator.add(1, 2); // static 메소드 이므로 객체 생성 없이 사용 가능
MyCalculator.min(1, 2); // static 메소드가 아니므로 객체 생성후에 사용가능

MyCalculator cal = new MyCalculator();
cal.add(1, 2); // o 가능은 하지만 권장하지 않는 방법
cal.min(1, 2); // o</code></pre>
<h3 id="static-변수">Static 변수</h3>
<ul>
<li>메모리에 고정적으로 할당되어, 프로그램이 종료될 때 해제되는 변수</li>
<li>메모리에 한 번 할당되기 때문에 여러 객체가 해당 메모리를 공유하게 된다</li>
</ul>
<pre><code class="language-java">public class Person {
    private String name = &quot;Korea&quot;;

    public void printName() {
    System.out.println(this.name);
    }
}</code></pre>
<p>&#39;Korea&#39;에 사는 100 명의 데이터를 수집한다고 했을 때 100명이 사는 지역의 이름을 Korea라고 100 번 저장하지 않고 static을 사용하면 메모리 효율이 더 높아진다</p>
<pre><code class="language-java">public class Person {
    public static final String name = &quot;Korea&quot;;

    public static void  printName() {
    System.out.println(this.name);
    }
}</code></pre>
<h3 id="static-메소드">static 메소드</h3>
<ul>
<li>static 메소드에서는 static이 선언되지 않은 변수에 접근이 불가능</li>
<li>static 메소드는 객체의 생성 없이 접근하는 함수이므로 할당되지 않은 메모리 영역에 접근을 하므로 문제가 발생하게 된다 그러므로 static 메소드에서 접근하기 위한 변수는 반드시 static 변수로 선언되어야 한다</li>
<li><strong><a href="https://peemangit.tistory.com/397">Singleton Pattern</a></strong>
인스턴스가 오직 1 개만 생성되어야 하는 경우에 사용하는 패턴
<code>Singleton Pattern</code>을 구현할 때 멀티 스레딩 환경에서도 동작이 가능해야 하기 때문에 <code>Thread-safe</code>가 보장되어야 한다</li>
</ul>
<h2 id="singleton-pattern"><strong><a href="https://peemangit.tistory.com/397">Singleton Pattern</a></strong></h2>
<p>인스턴스가 오직 1 개만 생성되어야 하는 경우에 사용하는 패턴
<code>Singleton Pattern</code>을 구현할 때 멀티 스레딩 환경에서도 동작이 가능해야 하기 때문에 <code>Thread-safe</code>가 보장되어야 한다</p>
<p><a href="https://velog.io/@haero_kim/%ED%98%B9%EC%8B%9C-%EC%8B%B1%EA%B8%80%ED%86%A4%EC%9D%B4%EC%84%B8%EC%9A%94-%EC%A0%80%EB%8A%94-%EB%B2%99%EA%B8%80%ED%86%A4%EC%9D%B4%EC%97%90%EC%9A%94-%E3%85%8B%E3%85%8B%E3%85%8B">싱글톤 참고</a></p>
<ul>
<li><p>Singleton Pattern 방식</p>
<blockquote>
<p><strong>Thread-safe 란?</strong>
  멀티 스레드 환경에서 동작해도 원래 의도한 형태로 동작하는 코드</p>
</blockquote>
<h3 id="1-eager-initalzation">1) Eager Initalzation</h3>
<p>  static 키워드의 특징을 이용하여 <u>프로그램이 시작하는 시점에서 정적 바인딩을 통해 해당 공유 인스턴스를 메모리에 올려 사용</u>하는 방식</p>
<h3 id="2-lazy-initialization">2) Lazy initialization</h3>
<p>  이른 초기화 방식과 정반대로 클래스가 로드 되는 시점이 아닌 <u>인스턴스가 필요한 시점에 요청할 경우 동적 바인딩을 통해 인스턴스를 생성하는 방식</u> Thread-safe를 만족 시키기 위해서 synchronized 키워드를 사용한다 <u>사용 전까지 메모리를 차지하지 않는 장점</u>이 있다</p>
<h3 id="3-lazy-initialization--double-checking-lockingdcl-thread-safe">3) Lazy Initialization + Double Checking Locking(DCL, Thread-safe)</h3>
<p>  위 방법은 많은 thread 들이 인스턴스를 호출할 경우 성능 저하가 발생하기 때문에 이를 개선한 방법이다.</p>
<p>  이 방식은 <u>인스턴스가 생성되지 않은 경우에만 동기화 블럭이 실행되게끔 구현하는 방식</u>이다</p>
  </div>
  </details>

<ul>
<li><p><strong>지역 변수, 전역 변수</strong>
변수는 &quot;선언위치&quot;에 따라 전역변수와 지역변수로 나눠진다.</p>
</li>
<li><p>전역변수(Global variable) : 어느 위치에서든 호출하면 사용이 가능
(함수 밖에 선언하여 클래스 전체에서 사용이 가능한 변수)</p>
</li>
<li><p>지역변수(Local variable) : 특정구역({ }) 내에서 생성되어 그 구역에서만 사용
(함수 속에 선언되어 해당 함수 속에서만 사용이 가능한 변수)</p>
<pre><code class="language-java">public class HelloAndroid {
  //메소드 밖에 있는 변수는 전역변수
  //전역변수의 생명주기는 클래스 끝

  static String strr = &quot;전역변수&quot;;

  public static void main(String[] args) {
      System.out.println(strr);

      String local = &quot;지역변수&quot;;
      //메소드 안에 넣어준 변수는 지역변수
      //지역변수는 해당하는 메소드만 사용

      System.out.println(local);

      method1();
  }
  public static void method1() {
      System.out.println(strr);
      //전역변수라 출력 가능

      //System.out.println(local);
      //지역변수이기에 출력 불가. 에러발생
  }
}</code></pre>
<h3 id="1-전역-변수">1) 전역 변수</h3>
</li>
<li><p>인스턴스 변수
클래스 영역에 선언되어 객체가 생성될 때마다 만들어지고 생성되었을 때만 호출하여 사용할 수 있음</p>
<pre><code class="language-java">
public class ChangeMoney {
      int a;
          //변수 선언
  public static void main(String[] args) {

      ChangeMoney ob = new ChangeMoney();
          //이곳에서 사용할 수 있게 선언해준다

      System.out.println(&quot;int a     :&quot; + ob.a);
             // 전역 변수는 초기화 하지 않아도 자바가 자동으로 해줌..
  }
}</code></pre>
</li>
<li><p>static 변수
객체를 따로 생성하지 않아도 사용 가능 많으면 실행 속도에 악영향</p>
<pre><code class="language-java">public class ChangeMoney {
  static
      int a;
          //변수 선언
  public static void main(String[] args) {

      //ChangeMoney ob = new ChangeMoney();
          //static을 해주면 선언 안해줘도 이곳에서 사용할 수 있다

      System.out.println(&quot;int a     :&quot; + ob.a);
  }
}</code></pre>
</li>
</ul>
</li>
</ul>
<h2 id="변수의-scope와-life-cycle"><strong><a href="https://catch-me-java.tistory.com/18">변수의 scope와 life cycle</a></strong></h2>
<ul>
<li><p>변수의 scope</p>
<blockquote>
<p><strong>scope란?</strong>
  선언된 변수, 클래스 등의 사용 범위</p>
<p><img src="https://images.velog.io/images/soooh_42/post/30b6b6ee-976a-414a-b949-6d1dc6e1bb68/image.png" alt="https://images.velog.io/images/soooh_42/post/30b6b6ee-976a-414a-b949-6d1dc6e1bb68/image.png"></p>
</blockquote>
<ul>
<li>Class 안에 var1이란 변수가 선언 됬으면 var1의 스코프는 클래스 전체에서 놀 수 있다. 즉, foo() 메소드 안에서도 들어갈 수 있다</li>
<li>하지만 var2는 어떨까? 저 변수의 스코프는 foo() 안에서의 초록색 칸에서만 사용할 수 있다. 즉, 반대로, var2의 집은 foo() 로 한정되어 있으므로, 집밖으로 나갈 수 없다</li>
</ul>
</li>
<li><p>변수의 life cycle</p>
<blockquote>
<p>Tlife cycle 란?
  모든 변수는 생명 주기를 갖는다</p>
<p><img src="https://images.velog.io/images/soooh_42/post/16b07750-5dbf-4aea-9f72-f36a705755ee/image.png" alt="https://images.velog.io/images/soooh_42/post/16b07750-5dbf-4aea-9f72-f36a705755ee/image.png"></p>
</blockquote>
<ul>
<li>인스턴스 변수는 객체가 생성될 때, 변수가 생성된다. 즉, 현재 Test 클래스를 static main 메소드나 다른 클래스에서 인스턴스를 생할 때 생성이 된다.
그리고 인스턴스는 참조가 없을 때 가비지 컬렉터가 객체를 지워버리게 되는데 이때, 인스턴스 변수도 같이 소멸된다.</li>
<li>매개변수는 예를들어 저 코드의 foo() 의 메소드가 호출 될 때 var3가 생성되고 foo() 의 메소드가 종료 시점에 var3로 소멸 된다.</li>
<li>지역변수 Local 변수는 ‘ { ‘ 가 시작되는 시점에 생성되며, ‘ } ‘ 로 끝나는 시점에 소멸된다.</li>
<li>정적변수는 클래스가 처음 호출 되면서 생성이 되고, 자바 어플리케이션이 종료되는 시점에 같이 소멸된다</li>
</ul>
</li>
</ul>
<h2 id="얕은-복사-깊은-복사"><strong><a href="https://jackjeong.tistory.com/100">얕은 복사, 깊은 복사</a></strong></h2>
<p>얕은 복사 - <code>주소 값</code>을 복사한다 (참조하는 실제 값은 같다)
깊은 복사 - <code>실제값</code>을 새로운 메모리 공간에 복사한다 (실제값이 다르다)</p>
<ul>
<li><strong><a href="https://life-with-coding.tistory.com/418">ArrayList 클래스</a></strong>
Collection 프레임워크의 List인터페이스의 제너릭 클래스를 배열 형태로 관리할 수 있도록 하는 클래스로 <code>순차적으로 자료를 저장</code>하여 관리하는 프로그램을 구현할 때 사용되는 클래스</li>
<li><strong><a href="https://gun1127.tistory.com/20">JavaDoc</a></strong>
java 소스에 문서화를 하는 방법으로 클래스나 메소드에 주석으로 기술한 내용을 javadoc 명령어나 이를 이용한 빌드 툴을 사용하여 문서화할 수 있다</li>
<li><strong><a href="https://bigcandle.tistory.com/72">Enhanced For Loop</a> (향상된 for문)</strong></li>
</ul>
<ol>
<li>기존 For Loop</li>
</ol>
<p><code>for(초기값 ; 조건식 ; 증감식) { // }</code>
2. 향상된 Enhanced For Loop</p>
<p><code>for(초기화 : 배열) { // }</code></p>
<h3 id="enhanced-for-loop-장단점">Enhanced For Loop 장단점</h3>
<p>장점 :</p>
<ol>
<li>배열의 크기를 조사할 필요가 없다.</li>
<li>반복문 본연의 반복문 구현에 집중하여 구현할 수 있다.</li>
</ol>
<p>단점 :</p>
<ol>
<li>배열에서만 사용가능하고, 배열의 값을 변경하지 못한다.</li>
</ol>
<p>썸네일: <a href="https://velog.io/@oneook/%EC%8D%B8%EB%84%A4%EC%9D%BC-%EB%A9%94%EC%9D%B4%EC%BB%A4Thumbnail-Maker-Toy-Project">oneook</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[42_JAVA Study 02]]></title>
            <link>https://velog.io/@soooh_42/42JAVA-Study-02</link>
            <guid>https://velog.io/@soooh_42/42JAVA-Study-02</guid>
            <pubDate>Fri, 10 Dec 2021 06:38:51 GMT</pubDate>
            <description><![CDATA[<h1 id="2주차-서브젝트">2주차 서브젝트</h1>
<h3 id="1-윤년-계산기-만들기">1. 윤년 계산기 만들기</h3>
<p><code>#private</code> <code>#information hiding</code> <code>#encapsulation</code> <code>#접근제어자</code> <code>#getter/setter</code></p>
<h3 id="2-this-예제-만들기">2. this 예제 만들기</h3>
<p><code>#this</code> <code>#생성자에서 this 사용할 때 주의 할 점</code></p>
<h3 id="3-참조-자료형-변수">3. 참조 자료형 변수</h3>
<p><code>#클래스 분리</code></p>
<h3 id="4-개체-협력">4. 개체 협력</h3>
<p><code>#객체 단일성</code></p>
<p>뒤늦게 노션에 정리하기 시작해서 미처 다 기록을 하지 못했다 ㅠㅜ</p>
<p>썸네일: <a href="https://velog.io/@oneook/%EC%8D%B8%EB%84%A4%EC%9D%BC-%EB%A9%94%EC%9D%B4%EC%BB%A4Thumbnail-Maker-Toy-Project">oneook</a></p>
]]></description>
        </item>
    </channel>
</rss>