Chapter.6 상속 기본

  • 상속이란?
    • 상속(Inheritance)
      • 객체 단위 코드를 '재사용'하는 방법, C++클래스가 C의 구조체와 구별되는 근거!
      • 두 클래스 사이의 '관계'를 고려해 프로그램 작성
    • 기본 문법
      • [class 파생클래스이름 : 접근제어지시자 부모클래스 이름]
        • ex) class MyData{ }; class MyDataEx : public CMyData { };
        • CMyDataEx 클래스는 CMyData 클래스를 상속받아 생성된 파생클래스가 된다, 
      • 파생 클래스 인스턴스가 생성될 때 기본 클래스(부모 클래스)의 생성자도 호출된다
        • 호출의 순서 1. 파생 클래스 생성자, 2. 부모 클래스 생성자
        • 실행의 순서 1. 부모 클래스 생성자, 2. 파생 클래스 생성자
      • 파생클래스는 기본클래스의 멤버에 접근 가능(private 제외)
      • 사용자 코드에서는 파생클래스의 인스턴스로 기본 클래스 메서드를 호출할 수 있다
    • 메서드 재정의
      • 오버라이드(override) 메서드를 재정의 하면 기존의 것이 무시된다(대체된다)
      • 기본 문법 및 특징
        • 재 정의시 기본형식의 메서드를 호출하려면 반드시 소속클래스를 정의해야 한다 (그렇지 않으면 재귀호출 발생함)
          • ex) CMyData::SetData(10);
        • 재정의 한 이유 : 제거 X, (기존 메서드 + 현재 메서드) 묶어 한꺼번에 작동 시키기 위함이다
        • 명시적 호출 : b.CMyData::SetData(15); // 메서드가 재 정의 되있어도 해당 클래스의 메서드가 실행된다
        • 묵시적 호출 : b.SetData(15);
          • 상위 클래스 참조자 형식으로 파생클래스에 대입했을 때 ( + 포인터도 )
          • ex) CMydata &rdata = a; // CMydata a;
          • rData.SetData(15); // CMyDataEx()의 SetData() 가 오버로드 됬으나 CMyData의 메서드가 실행됨
    • 상속에서의 생성자와 소멸자
      • 과정 
        1. 파생 클래스 생성자가 호출된다
        2. 파생 클래스 생성자가 실행되기 전에 부모 클래스의 생성자를 호출한다
        3. 부모 클래스 생성자가 실행되고 반환된다
        4. 파생 클래스의 생성자가 실행되고 반환된다
        5. 소멸은 생성의 역순(A -> B -> C | C -> B -> A)
          • 따라서 파생 클래스 에서 부모 클래스의 멤버변수에 쓰기, delet 연산을 하면 안된다!!!
          • 파생 클래스 생성자에서 부모 클래스 맴버 변수를 초기화 하지 않는다.
      • 생성자 선택
        • '생성자 상속'
          • 다중 정의된 상위 클래스의 생성자들을 그대로 가져오는 문법
            • ex)CMyDataEx(int nParam) : CMyData(nParam) { ~ } 
              • 파생 클래스 생성자 실행 전에 부모 클래스 생성자 호출함

 

 

 

 

 

'IT공부 > 이것이 C++이다' 카테고리의 다른 글

객체지향 프로그래밍_2  (0) 2022.03.12
객체지향 프로그래밍_1  (0) 2022.03.11
C에서 C++ 문법 전환하기_2  (0) 2022.03.09
C 에서 C++로 문법 전환하기_1  (0) 2022.03.07

Chapter.4 복사 생성자와 임시 객체

(난이도 매우 높으니 여러번 복습할 것)

  • 복사 생성자
    • 복사 생성자란? : 객체의 복사본을 생성할 때 호출되는 '생성자'
      • 생략하면 디폴트 생성자 처럼 컴파일러가 알아서 만들어 넣어줌
      • 클래스 내부에서 메모리를 동적할당 및 헤제, 멤버포인터 변수로 관리 한다면 문제가 생긴다
        • ex) 클래스 내부에 new 로 변수 사용
      • 사용법 [ 클래스 이름( const 클래스 이름 &rhs); ]
        • 이때 const는 생략 가능하지만, 원본 객체를 손상시키지 않기 위해 const를 꼭 선언해주자! 
    • 복사 생성자 정리 ( 모든 상황 )
  1. 복사 생성자 (깊은 복사)
    1. 명시적 객체의 복사본 생성
    2. 함수의 형태로 호출
      1. 클래스가 함수의 매개변수로 사용 (무조건 참조 형태로 선언하기!)
      2. 클래스가 함수의 반환형태로 사용 (이름 없는 객체 생성됨!)
  2. 이동 시멘틱 (얕은 복사)
    1. 이동생성자
    2. 이동 대입연산자
  • 복사 생성자(게속)
    • 클래스가 함수의 매개변수로 사용되는 경우
      • 문제 : 의미없이 class 객체가 2번 사용됨
        1. 객체 선언시 1개 ( 함수의 인수로 넣기 위해 선언 )
        2. 함수의 매개변수로 클래스 객체를 받을때 다시 생성된 1개 ( 함수 내부에서 사용하기 위해 선언 )
      • Solution.1 : 복사 생성자 삭제(delete)
        • CTestData(const CTestData &rhs) = delete; 선언하기
        • 복사 생성이 아예 불가능하게 막아버림
      • Solution.2 : 참조자 사용 (&)
        • 매개변수로 클래스 객체를 받는 함수에서 매개변수로 클래스 객체의 참조자를 받는 함수로 변환시키기
        • ex) void TestFunc(CTest param) -> void TestFunc(const CTest &param) // 객체 생성은 1번만 됨
          • 이때도 const선언은 생략 가능하지만, 원본 객체를 손상시키지 않기 위해 const를 꼭 선언해주자! 
    • 깊은 복사와 얕은 복사
    • 얕은 복사는 메모리 관련 문제가 생긴다(둘다 delet 사용시 하나에 2번사용, 하나는 남아있는 상태가 되기 때문)
깊은 복사 얕은 복사
값이 2개, 각각 포인터 1개씩 값이 1개, 하나에 포인터 2개
int *pA, *pB;
pA = new int; / pB = new int;
*pA = 10;
*pB = *pA; pB = pA;
  • 복사 생성자(게속)
    • 대입 연산자
      • 단순 대입 연산자(=) 가 구조체나 클래스에도 기본적으로 적용됨
      • 하지만 단순 대입 연산자는 '얕은 복사' 가 수행된다!
      • 따라서 이때 연산자 다중 정의를 사용하여 문제를 해결해 주면 된다(나중에 배울 것)
        • ex) CMyData& operator=(const CMyData &rhs) { *m_pnData = *rhs.m_pnData; return *this; }
        • a = b (a.operator=(b) 와 같은 형식으로 호출 가능)
  • 묵시적 변환
    • 묵시적 변환이란?
      • 직접적인 언급은 없었으나 당연하게 변환 하는 것
    • 변환 생성자
      • 매개변수가 하나인 생성자를 '변환 생성자' 라고 한다!
      • ex) CTestData(int nParam) { ~ } // 변환 생성자
        • void TestFunc(CTestData param) { } / TestFunc(5); // 변환생성자 사용됨 
        • 원래 클래스를 맴버변수로 받지만, int 형으로 받음
      • 이는 실제로 임시 객체가 생성되어 전달된 것 즉 TestFunc(CTestData(5)) 와 동일한 의미를 가진다
      • 묵시적 변환 생성자는 편의성은 좋아지지만 효율성(성능)은 낮아진다
      • 이때 변환생성자 앞에 explicit 예약어를 사용하면 묵시적 변환이 불가능해진다(임시 객체 생성 X)
        • explicit CTestData(int nParam) { ~ }
    • 허용되는 변환
      • 변환 생성자가 있으면 int 자료형 -> CTestData 자료형 은 가능했다
      • 그러나 CTestData 자료형 -> int 자료형 은 불가능하다 이때 형변환 연산자를 사용하면 가능해진다
        1. operator int(void) { return m_nData; } / a 
        2. int(a) // 무조건 강제 변환 시킴 
        3. static_cast<int>(a) // 예외 상황을 제외하고는 변환 시켜줌
      • 웬만하면 static_cast<자료형>(이름) 으로 명시적 형변환을 사용하자!
    • 임시 객체와 이동 시멘틱
      • 함수의 반환 형식이 클래스인 경우
        • 함수의 반환형식이 클래스인 함수를 실행시키면 _tmain(메인함수)에 이름없는 객체가 생성, 소멸 된다
        • 함수를 반환(return) 하면서 생성, 대입 연산이 끝나면서 소멸 한다
          • 이때 '무조건' 이름없는 객체가 생성, 소멸 한다
        • '이름없는 임시 객체의 원본 = 임시 객체의 복사 생성이 끝난 후'
        • 이때 소멸 전에 연산이 가능하다 ex)TestFunc(10).GetData()
        • 이름없는 객체에 별칭을 부여해서 소멸 시점을 달라지게 할 수 있다
          • CTestData &rData = TestFunc(10) // 클래스 참조자 변수로 별칭을 부여! (소멸 시기를 인식하자)
      • r-value 참조
        • 3에4를 대입할 수 없듯 변수가 아닌 대상에 참조를 선언하는것은 허용되지 않는다
        • 그러나 C++11 표준 등장후 r-value 에 관한 참조자가 새로 제공됬다 ( int &&) 형식
        • 여기서 r-value : 연산자 따라 생성된 임시 객체!
        • 아래 표를 보고 어떤 상황에 무엇이 필요할지 선택해서 사용할 것
매개변수 형식 실인수 예 비고
TestFunc(int) int x=3; TestFunc(x); / TestFunc(3) / 
TestFunc(3+4);
 
TestFunc(int &) int x=3; TestFunc(x)  
TestFunc(int &&) int x=3; TestFunc(3); / TestFunc(3+4); / TestFunc(x + 4); 이때 TestFunc(x)는 불가능!
  • 묵시적 변환 게속
    • 이동 시멘틱
      • 이동 생성자 + 이동 대입 연산자
      • 복사생성자와 대입 연산자에 r-value 참조를 조합하여 새로운 생성자가 만들어 졌다
      • 이동 생성자 [ CTestData(CTestData &&rhs) { ~ } ] 복사생성자에 & 하나더
      • 만들어진 이유 : 얕은 복사를 하기 위해 (복사 생성자는 깊은 복사가 된다)

연습문제

1. 함수의 매개변수가 기본 형식이 아니라 클래스라면 매개변수 형식은 어떻게 정하는 것이 바람직한가? 그 이유는?

- 클래스의 참조자 형식, 의미없이 객체를 2번 할당(선언) 하지 않기 위해

2. 복사 생성자 및 단순 대입 연산자를 반드시 정의해야 하는 클래스는 어떤 클래스인가?

- 클래스 내부에서 동적할당(new, delete) 를 사용하고, 이를 참조자로 관리하는 클래스

3. 만약 다음과 같은 코드에서 컴파일 오류가 없었다면 CTestData 클래스는 잠재적인 문제를 가진것, 그것이 무엇인가?

void TestFunc(const CTestData &param) { ~ }

int _tmain(int argc, _TCHAR* argv[]) {

    TestFunc(5);

    return 0;

}

- 변환 생성자가 활용된다 -> 성능에 대한 문제

4. 이동 시멘틱이 등장한 가장 큰 원인은 무엇인가?

- 얕은 복사를 사용해서 메모리 공간을 효율적으로 사용하기 위해

 

'IT공부 > 이것이 C++이다' 카테고리의 다른 글

객체의 관계 규정과 설계_1  (0) 2022.03.16
객체지향 프로그래밍_1  (0) 2022.03.11
C에서 C++ 문법 전환하기_2  (0) 2022.03.09
C 에서 C++로 문법 전환하기_1  (0) 2022.03.07

Chapter.3 클래스

  • 객체지향 프로그래밍 개요
    • 객체란 변수들과 그와 관련된 메서드들이 모여서 이룬 하나의 꾸러미! ( 객체 = 동작이나 상태를 나타내는 단위 )
    • 클래스란 C의 구조체에서 확장된 변수, 함수를 포함한 하나의 틀 이다 ( 클래스 = 찍어내기 위한 틀 )
    • 인터페이스 함수 : 내부로 직접 접근 못하는 사용자를 대신하여 내부안에서 기능을 수행하게 해주는 함수
  • 클래스의 기본 문법
    • 클래스의 기본 형태
      • class 클래스 이름    {
      • 접근제어 지시자:    // public, private, protected
      •     맴버변수 선언;
      •     맴버함수 선언 및 정의;
      • };
    • 맴버 선언 및 정의
      • 클래스는 '생성자'를 이용해 초기화 할 수 있음! - 생성자의 특징
        1. 반환하는 자료형이 없다
        2. 호출하는 함수가 아니라 적절한 시기에 자동으로 호출되는 함수
      • '사용자가 객체를 선언하면 자동으로 호출됨!' -> 따라서 맴버가 자동으로 초기화 가능
      • 선언법 // 클래스와 같은 이름의 함수를 선언 해주면 됨 
        • class Ctest {
        • public:
        •     Ctest() { ~ }
        • }
      • 생성자 사용시 초기화 목록 이용하는 법 -> 생성자 선언 뒤 콜론: 입력후 변수(값) 의 형태로 입력한다
        • class CTest {
        • public:
        •     CTest() : m_nData(10), m_nData2(20) { ~ }
        • }
    • 접근제어 지시자
      • 클래스의 특정 요소에 사용자가 접근할 수 없게 하기 위해 활용한다
        1. public : 멤버에 관한 모든 외부 접근이 허용됩니다
        2. protected : 멤버에 관한 모든 외부 접근이 차단됩니다 단 상속 관계가 있는 파생 클래스에선 접근 허용
        3. private : 외부 접근, 파생 클래스 접근 차단, 별도의 접근제어 지시자가 없을때 private로 간주됨
      • 이때 생성자도 접근제어 지시자의 영향을 받는다 ( 별도의 목적이 없다면 생성자는 public 으로 설정하자 )
  • 생성자와 소멸자
    • 객체가 생성, 소멸될 때 '자동으로' 호출됨, 반환 형식이 없음, 함수와 이름이 같다(소멸자의 경우 ~함수이름() 이다)
    • 매개변수가 없는 생성자를 디폴트 생성자 라고 한다
    • 생성자와 소멸자를 기술하지 않으면 컴파일러가 알아서 디폴트 생성자와 소멸자를 넣어준다
    • 선언된 블록 범위가 끝나면 자동으로 소멸된다 ex) 메인에서 호출후, 메인이 끝나면 -> 소멸자가 실행된다
      • main() 함수가 호출되기 전에 생성자가 호출될 수 있다(전역 변수로 선언한 클래스의 경우)
      • 생성자는 다중 정의 할 수 있다 (오버로딩)
      • 소멸자는 다중 정의 할 수 없다
      • main() 함수가 끝난 후에 소멸자가 호출될 수 있다
      • 생성자와 소멸자는 생략할 수 있으나 생략할 경우 컴파일러가 디폴트 생성자와 소멸자를 만들어 넣는다
      • 새로운 생성자를 만들면 디폴트 생성자를 생략할 수 있다(컴파일러도 만들어 주지 않음)
    • 동적 객체의 생성과 소멸
      • C++에서 동적 객체의 생성과 소멸은 new 와 delete 이다
      • 이때 클래스를 동적 객체로 생성하면, new 실행시 생성자가, delete 실행시 소멸자가 실행된다
    • 참조 형식 멤버 초기화
      • 참조자는 반드시 선언과 동시에 초기화 해야한다!
      • 이때 생성자 초기화 목록을 이용해 초기화 해야 한다
        • ex) CTest(int &rParam) : m_nData(rParam) { }; // int &m_nData(참조형 맴버변수)
    • 생성자 다중 정의
      • 생성자는 다중 정의 할 수 있다
      • 이때 생성자 위임 이라는 편리한 기능을 사용할 수 있다 
        • ex) CMyPoint(int x) { ~ } / CMyPoint (int x, int y) :CMyPoint(x) { ~ }
        • 즉 생성자 CMyPoint 실행 시 생성자 CMyPoint(int x) 또한 추가로 호출 될 수 있도록 위임 한 것
    • 명시적 디폴트 생성자
      • 디폴트 생성자가 필요할 때 다중 정의를 해 놓으면 디폴트 생성자가 만들어 지지 않으므로, 일부러 명시 해 준다
      • ex) CTest(void) = default; // CTest() 라는 생성자는 디폴트 생성자 이다!
      • delete 로 생성자 함수를 삭제할 수도 있다 ex) CTest(void) = delete; // 디폴트 생성자 삭제
  • 메서드(Method)
    • 매서드 = 맴버 함수 = 인터페이스 함수 // 클래스가 제공하는 기능! 방법! 을 뜻한다
    • this 포인터
      • 작성중인 클래스의 실제 인스턴스에 대한 주소(본인)
종류 일반 상수화 정적 가상
관련 예약어 - const static virtual
this 포인터 접근 가능 가능 불가능 가능
일반 멤버 읽기 가능 가능 가능(제한적) 가능
일반 멤버 쓰기 가능 불가능 가능(제한적) 가능
적정 멤버 읽기 가능 가능 가능 가능
적정 멤버 쓰기 가능 불가능 가능 가능
특징 보편적인 메서드 멤버 쓰기 방지가 목적 C의 전역함수와 유사 상속 관계에서 의미
    • 상수형 메서드
      • 멤버 변수에 읽기 접근은 가능하지만 쓰기는 허용하지 않은 메서드
      • ex) int GetData() const { ~ } // 이렇게 함수의 원형 뒤에 const 만 선언해 주면 된다
    • 상수형 메서드의 예외사항
      • 상수화 된 메서드 로도 멤버변수에 접근할 수 있게 맴버변수 선언을 해준다
        • mutable int m_nData = 0; // mutable 선언으로 GetData
      • 상수형 참조를 일반 참조로 형변환 한다
        • const int &nParam 으로 입력받은 것을 int &nParam 으로 변경시킴
        • int &nNewParam = const_cast<int &>(nParam);
        • [ const_cast<새형식> (대상) ]
    • 멤버 함수 다중정의
      • 메서드 또한 다중정의 될 수 있다
      • 다중정의시 잘못된 실 인수가 들어오면 delete 로 과감히 삭제하자
        • ex) void GetIntData(double dParam) = delete; // double 형 실인수가 들어오면 소멸자 실행
    • 정적멤버
      • 정적 변수는 전역변수나 함수와 마찬가지, this 포인터 사용 불가
      • static 예약어로 사용 ex) static int GetCount(); / static int m_nCount; / int CTest::m_nCount = 0;
      • 이때 정적변수는 반드시 선언과 정의를 분리해야 한다
        • 원래 CTest a(5) 선언 후 a.GetCount(); 로 선언해야 하지만 그냥 GetCount(); 로 정적 멤버에 접근 가능하다

연습문제

1. 클래스 접근 제어 지시자 중에 private 이 의미하는 것은 무엇인가? = 외부, 상속 클래서에서 접근 불가

2. 클래스 인스턴스가 생성될 때 자동으로 호출되는 함수와 그 함수의 원형의 가장 큰 특징은? = 생성자, 반환형이 없다

3. 다음 코드에서 m_nData(nParam) 이 속한 부분을 무엇이라 부르는지 답하시오 = 초기화 목록

CTest(int nParam)

    : m_nData(nPatam) // 초기화 목록

{ ~ }

4. 다음 코드에서 잘못된 점과 개선방법 = 참조형 변수를 초기화 할때는 초기화 목록으로 초기화 해야 한다 CRefTest(int &rPatam) : m_nData(rParam) { ~ }

5. 메서드 함수 내부에서 실제 클래스 인스턴스의 주소를 가리키는 포인터는? = this

6. 상수형 메서드에서 할 수 없는 일은 무엇인지 답하세요 = 멤버변수 쓰기(읽기는 허용)

7. 정적 멤버에서는 '이것'을 사용할 수 없다. 이것은? = this 포인터

'IT공부 > 이것이 C++이다' 카테고리의 다른 글

객체의 관계 규정과 설계_1  (0) 2022.03.16
객체지향 프로그래밍_2  (0) 2022.03.12
C에서 C++ 문법 전환하기_2  (0) 2022.03.09
C 에서 C++로 문법 전환하기_1  (0) 2022.03.07

Chapter.2 C++ 함수와 네임스페이스

  • 디폴트 매개변수
    • C에서는 함수를 호출하려 한다면 매개변수의 실 인수를 기술해야한다
    • C++에서는 매개변수의 초깃값을 설정해서 입력이 없을 경우 초깃값을 대입해 준다
      • 따라서 호출자를 보고 함수의 원형을 확정하면 안됨!!
      • ex) int TestFunc(int nParam = 10) // = int TestFunc(int = 10) 
      • 이때 함수 원형의 선언 부분에 기술해야하고, 정의 부분에 기술하면 컴파일 오류가 발생한다 // 선언부분 변수 이름 생략 가능
    • 매개변수 선언시 규칙
      1. 피호출자 함수 매개변수의 디폴트 값은 반드시 오른쪽 매개변수 부터 기술해야 한다
      2. 매개변수가 여려 개일 때 왼쪽 첫번째 매개변수의 디폴트 값을 기술하려면 나머지 오를쪽 모든 매개변수에 대한 디폴트 값을 기술해야 하며, 절대로 중간에 빼먹으면 안된다!
      3. 호출자 함수가 피호출자 함수 매개변수의 실인수를 기술하면 이는 왼쪽부터 짝을 맞추어 적용되며, 짝이 맞지 않은경우 매개변수는 디폴트 값을 적용한다
    • 모호성을 조심할 것, 가급적 디폴트 매개변수 사용을 지양할 것
  • 함수의 다중 정의
    • 다중정의, Overloading 은 함수의 다형성을 지원(편의성, 확장성)
      • 함수의 구성 요소 = 반환형식 호출규칙 함수이름(매개변수, 매개변수 ...);
    • 이때 다중정의, 오버로딩을 하기 위해선 매개변수를 제외한 모든 것은 동일해야 한다!!
    • 다중정의의 모호성
      • 다중정의와 디폴트 매개변수가 조합되면 '모호성'이 발생할 수 있다
        • ex) void TestF(int a) { ~ } / void testF(int a, int b = 10) { } 
        • 이때 TestF(5); 를 선언한다면 컴파일 오류가 발생한다( 모호성 때문)
    • 함수 템플릿(template)
      • 오버로딩으로 여러 함수를 만들기 보다 템플릿으로 만드는 것이 더 효율적이다
      • 템플릿은 일종의 '틀' / 함수를 찍어내기 위한 
        • ex) template <typename T> / T TestFunc(T a) { } // T는 자료형
        • 이때 testFunc을 호출하는 매개변수(실인수)의 자료형에 따라 T가 정해진다!
    • 인라인 함수(inline)
      • 인라인 함수 = (함수의 장점 + 매크로(#define) 의 장점) 이다
      • 함수의 원형 앞에 inline 예약어만 작성하면 된다
        • ex) inline int TestFunc(int a) { ~ }
      • 코드가 일정 수준 이상으로 길어지면 인라인 함수보다 그냥 함수가 더 효율적
      • 이는 컴파일러가 판단하여 인라인함수 <-> 일반 함수 로 바꿔서 컴파일 할 수 있다
    • 네임스페이스(namespace)
      • C++가 지원하는 각종 요소들(변수, 함수, 클래스 등)을 한 범주로 묶어주기 위한 문법
      • 소속, 구역 등으로 이해 (이름의 성 같은 존재)
        • 네임스페이스 선언 : namespace 이름 { ~ } // ~ 안에 변수, 함수, 클래스 가 들어갈 수 있다
        • 네임스페이스의 중복 선언이 가능하다 
        • 네임스페이스가 없는 함수는 '전역 네임스페이스'에 속한다
      • using 선언
        • namespace를 생략하기 위한 예약어
          • using namespace std; // std::cin 이라고 호출해야 했던 함수를 cin 으로도 호출할 수 있게 해줌
      • 같은 함수, 변수 등 이어도 namespace가 다르면 전혀 다른 개체로 인식된다
      • 네임스페이스와 다중정의
        • 다중 정의의 조건은 이름이 같아야 한다, 이때 이름이 같다는 것은 namespace도 같다는 뜻을 포함한다
        • 이름이 같고, 모든것이 같아도 namespace가 다르면 다른 개체! // 이때 호출시 네임스페이스를 구별해 주지 않으면 모호성에 의해 컴파일 오류가 발생한다
    • 식별자 검색 순서
      • 식별자가 선언된 위치를 검색하는 순서 // 이때 호출자보다 먼저 선언되야 함(윗줄에 존재해야함)
      • 전역 함수읜 경우
        1. 현재 블록 범위
        2. 현재 블록 범위를 포함하고 있는 상위 블록 범위(Max는 함수 몸체)
        3. 가장 최근에 선언된 전역변수 나 함수
        4. using 선언된 네임스페이스 혹은 전역 네임스페이스 / 이때 두 곳에 동일한 식별자 존재 시 컴파일 요류
      • 클래스 메서드인 경우
        1. 현재 블록 범위
        2. 현재 블록 범위를 포함하고 있는 상위 블록 범위(Max는 함수 몸체)
        3. 클래스의 멤버
        4. 부모 클래스의 멤버
        5. 가장 최근에 선언된 전역 변수나 함수
        6. 호출자 코드가 속한 네임스페이스의 상위 네임스페이스
        7. using 선언된 네임스페이스 혹은 전역 네임스페이스 / 이때 두 곳에 동일한 식별자 존재 시 컴파일 요류

연습문제

1. 다음 두 함수 원형에서 잘못된 점은 무엇인지 답하세요

- int TestFunc(int nParam1 = 5, int nParam2, int nParam3 = 10) 

- int TestFunc(int nParam1 = 5, int nParam2) 

= 초깃값 설정은 오른쪽부터, 중간에 빼먹을 수 없음

2. 다음 두 함수를 호출하는 코드에서 문제가 발생하는 이유

void TestFunc(int a) { std::cout << "TestFunc(int)" << std::endl; }

void TestFunc(int a, int b = 10) { std::cout << "TestFunc(int, int)" << std::endl; }

 = 함수의 모호성이 발생하기 때문( TestFunc(10) 실행시 모호성 오류 발생 )

3. 함수를 다중정의 하는것보다 템플릿이 더 좋은 코드가 될 가능성이 높은 이유?

= 템플릿으로 함수를 작성하면 유지보수 및 관리가 쉬워진다(다중정의는 N개를 바꿔야함, 템플릿은 하나만 바꾸면 됨)

4. inline 함수와 매크로의 공통된 장점

= 대입한다( 메모리 사용량이 낮아진다 )

5. 네임스페이스 미리 선언하는 법

= using namespace

6. 다음 코드의 실행결과

#include <iostream>

using namespace std;

 

int nData = 200;

 

namespace Test {

    int nData = 100;

    void TestFunc(void) {

        cout << nData << endl; // 여기서의 nData가 가리키는 것은? 1은 없음, 2로 100

    }

}

 

int _tmain(int argc, _TCHAR* argv[]) {

    TEST::TestFunc(); // 연산자 찾기

 

    return 0;

}

 

 

= 100

 

'IT공부 > 이것이 C++이다' 카테고리의 다른 글

객체의 관계 규정과 설계_1  (0) 2022.03.16
객체지향 프로그래밍_2  (0) 2022.03.12
객체지향 프로그래밍_1  (0) 2022.03.11
C 에서 C++로 문법 전환하기_1  (0) 2022.03.07

Chapter.1 C 와는 다른 C++

  • C와 C++의 차이
    • C언어의 자료형에 대한 핵심
      1. 정수형이나 문자형 같은 자료형: 자료형이 다르면 사용 불가능
      2. 구조체나 공용체: 기존의 자료형을 조합해 새로운 형식의 자료형을 만들어 활용할 수 있다
      3. 포인터: 자료형을 효율적으로 다루기 위해 메모리를 어떻게 이용하는지 이해하기 위한 핵심 개념
    • HellowWord로 본 C++
      • #include "stdafx.h" // standard application frameworks (표준 애플리케이션 프레임 워크) -> visual studio만 사용
      • #include <iostream> // C++ 에서는 표준 헤더파일을 추가할 때 .h 를 붙이지 않는다
      • std::cout << "Hellow World" << std::endl;
        1. std = 네임스페이스(namespace) 개념 상 소속!
        2. :: = 범위 지정 연산자, 스코프 설정 연산자(Scope resolution operator)
        3. cout = 콘솔 출력을 담상하는 객체
        4. << = 연산자 함수
        5. endl = C 언어의 \n 과 같이 개행의 역활 + Fflush와 같이 출력 스트림를 모두 내보내는 역활
          • C언어의 printf 함수보다 효율적 / 출력 전문 객체에게 출력을 맡기는 것 ex) 세탁 직접하기 -> 세탁소에 맡기기
    • 인스턴스와 입출력 흐름
      • 인스턴스(instance) 란? = 객체의 형식을 갖는 변수를 인스턴스 라 한다
      • std::cout
        • iostream 클래스의 인스턴스 이다
        • C와 가장 큰 차이점은 형식문자를 지정하지 않아도 된다는 것이다!
        • << 연산자로 여러 문자열을 추가로 이어 출력할 수 있다
          • ex) std::cout << "저는 " << 20 << "살 " << "입니다."" << std::endl; // 저는 20살 입니다.
      • std::cin
        • iostream 클래스의 인스턴스 이다
        • >> 연산자를 사용, 마찬가지로 형식문자를 지정하지 않아도 된다
          • ex) std::cin >> nAge; // 입력받은 문자, 문자열 등을 nAge 에 저장
    • 자료형
      • 변수의 선언 및 정의
        • int a = 10; = int a(10); // 초깃값이 상수가 아닌 변수 일 경우(int b(a)) 복사 생성자 사용됨
      • auto
        • 초깃값의 형식에 맞춰 선언하는 인스턴스의 형식이 '자동'으로 결정됨
    • 메모리 동적 할당
      • new와 delete 연산자
        • new 연산자 = 객체의 생성자 호출, delet 연산자 = 객체의 소멸자 호출 
        • 일반 변수 
          • 형식 *변수이름 = new 형식;
          • delete 변수이름
        • 배열인 변수
          • 형식 *변수이름 = new 형식[요소개수];
          • delete[] 변수이름;
    • 참조자 형식
      • 형식 &이름 = 원본; // 꼭 선언과 동시에 초기화 해야함 ( 상수에는 참조자 선언 불가 )
      • 포인터와 다르게 한번 짝을 이루게 되면 달라지지 않는다
      • 덩치가 큰 자료는 값이 아니라 '주소'를 전달하는 것이 효율적이기 때문에 존재한다, call-by-reference 가능
      • 호출자 코드로는 매개변수가 참조 형식인지 알 수 없다!
      • r-value 참조
        • int &&radata = 3;
        • r-value 참조자는 곧 사라질 대상에게 참조가 가능하다 ex) 3+2+1 이면 3+2가 먼저 계산된 후 5+1이 계산됨, 이때  5가 곧 사라질 대상
        • 추후 더 설명할 예정
    • 범위기반 for 문
      • for(auto 요소변수 : 배열이름) { 반복문 }
        • 배열의 요소 수에 따라 반복 횟수가 정해지고, 요소 변수는 각 배열의 n번째 요소에 접근하게 해준다
          • ex) int arr[5]; for(auto n : arr) // 5번 반복, 0번째는 n = arr[0], 2번째때 n=arr[2]; 이다
        • 배열의 요소를 변경하려면 &요소변수 형식으로 선언해야 한다
          • ex) for(auto &n : arr)
        • 배열이 바뀌었을 경우 반복문을 수정하지 않아도 되기 때문에 생산성이 향상된다

연습문제

1. 

string name;

int age;

 

cin >> name >> age;

cout << "나의 이름은 " << name << "이고, " << age << "살입니다." << endl;

 

2. auto 는 초깃값의 형식에 따라 자료형을 세팅해준다, ex) auto a(10); // = int a(10);

3. char *arr = new char[12]; / delete[] arr;

4. void swap(int &a, int &b) { int tmp; tmp = a; a = b; b = a; }

5. 기본 참조는 저장되어 있는 변수의 위치를 참조하는 것 이고, 상수형 참조는 곳 사라질 값, 즉 중간 계산 값(임시 결과)를 참조할 수 있다. 

 -- ??

6. for(auto n : aList) { cout << n << " ";} cout << endl;

 

 

'IT공부 > 이것이 C++이다' 카테고리의 다른 글

객체의 관계 규정과 설계_1  (0) 2022.03.16
객체지향 프로그래밍_2  (0) 2022.03.12
객체지향 프로그래밍_1  (0) 2022.03.11
C에서 C++ 문법 전환하기_2  (0) 2022.03.09

+ Recent posts