1. 반드시 이니셜라이저를 통해서 초기화하자. 생성자에서 대입 연산으로 초기화 하는 것은 초기화가 아닌 대입이다(이미 객체의 생성자가 기본값이나 쓰레기값으로 초기화를 한 후 다시 초기화하는 꼴이된다)


2. 사용자 정의 자료형이 아닌 기본제공 자료형은 초기화가 될수도있고 안되어 있을 수도 있다.(int, char, double 등등)


객체를 구성하는 데이터의 초기화의 순서는 

1. 기본 클래스는 파생 클래스보다 먼저 초기화된다.

2. 클래스 데이터 멤버는 그들이 선언된 순서대로 초기화된다(이니셜라이저 초기화 순서는 상관없다)


정적 객체

1. 전역 객체

2. 네임스페이스 유효범위 안에서 정의된 객체

3. 클래스 안에서 static으로 선언된 객체

4. 함수 안에서 static으로 선언된 객체

5. 파일 유효범위에서 static으로 정의된 객체

이중 함수안에 있는 객체는 지역 정적 객체라 하고 밖에 있는 객체는 비지역 정적 객체라 한다.


번역단위

컴파일을 통해 하나의 목적 파일(Object File)을 만드는 바탕이 되는 소스 코드. 즉 #include 파일들까지 다 합쳐서 기계어로 번역하는 단위.


비지역 정적 객체의 초기화 순서는 개별 번역 단위에서 정해진다.(순서는 랜덤, 즉 정해져있지 않다.)


두 비지역 정적 객체의 초기화 과정에서 연관관계가 있을 시, 초기화에 문제가 생긴다(누가먼저 초기화될지 모르니까)


해결책

싱글톤 패턴처럼 레퍼런스를 반환시켜주는 함수를 각각 만들고 적용시킨다.


정리

1. 기본제공 타입의 객체는 직접 초기화한다. 경우에 따라 저절로 되기도 하고 안되기도 하기 때문에


2. 생성자에서는, 데이터 멤버에 대한 대입문을 생성자 본문 내부에 넣는 방법으로 멤버를 초기화하지 말고 멤버 초기화 리스트(이니셜라이저)를 이용한다. 그리고 초기화 리스트에 데이터 멤버를 나열할 때는 클래스에 각 데이터 맴버가 선언된 순서와 똑같이 나열한다.


3. 여러 번역 단위에 있는 비지역 정적 객체들의 초기화 순서 문제는 피해서 설계해야 한다.

   함수를 이용해 비지역 정적 객체를 지역 정적 객체로 바꿔 사용한다.( 싱글톤패턴, 레퍼런스 반환      함수 )  





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

const 사용법  (0) 2015.01.28
Posted by 눈떠보니내무실
,

1. const 의 위치

void f1(const widget *pw)    //pw가 가리키는 값은 상수다.


void f2(widget const *pw)    //역시 pw가 가리키는 값은 상수다. 즉 위와 동일하다.


const vector<int>::iterator iter = vec.begin();    //iter는 T* const 처럼 동작한다.

*iter = 10;       //Ok. iter 가 가리키는 대상을 변경한다.

++iter;          //Error!, iter는 상수이기 때문에 변경이 불가능하다.


vector<int>::const_iterator iter = vec.begin    //iter는 const T*처럼 동작한다.

*iter = 10;       //Error!, iter 가 가리키는 대상은 상수다.

++iter;          //OK. iter 자체는 변수이므로 변경 가능.


2. 중복 코드 피하기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class TextBlock
{
public:
    ...
    
    const char& operator[](size_t position) const //상수 객체를 위한 operator
    {
        return text[position];
    }
    
    char& operator[](size_t position) //비상수 객체를 위한 operator
                                                          //, 중복을 막기위해 상수버전을 호출한다.
    {
        return
          const_cast<char&>(           //반환 타입의 const를 날려버린다
             static_cast<const TextBlock&>(*this)[position]);  //static_cast를 통해 상수 operator를 
                                                             //불러온다.
            //*this는 TextBlock인데 이걸 const TextBlock로 형변환 함으로서 상수 객체를 위한 operator
            //를 불러올 수 있게 되는 것이다. 그냥 operator[] 를 부르면 자기자신을 계속부르는 무한루프에
            //걸리게 된다.
    }
    ......
};


1. const를 붙여 선언하면 컴파일러가 사용상의 에러를 잡아내는 데 도움을 준다. const는 어떤 유효범위에 있는 객체에도 붙을 수 있으며, 함수 매개변수 및 반환 타입에도 붙을 수 있으며, 멤버 함수에도 붙을 수 있다.


2. 컴파일러 쪽에서 보면 비트수준 상수성을 지켜야 하지만, 우리는 개념적인(논리적인) 상수성을 사용해서 프로그래밍 해야 한다.


3. 상수 멤버 및 비상수 멤버 함수가 기능적으로 서로 똑같게 구현되어 있을 경우에는 코드 중복을 피하는 것이 좋은데, 이때 비상수 버전이 상수 버전을 호출하도록 만들어야 코드의 낭비가 없어진다.(2번의 예처럼)









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

객체 초기화  (0) 2015.01.28
Posted by 눈떠보니내무실
,

예외처리

Programming/C & C++ 2014. 6. 9. 16:59

예외상황

프로그램 실행 중에 발생하는 문제의 상황을 의미한다.

문법적인 오류가 아닌 예외의 상황

즉 예외는 문법적 오류가 아닌, 프로그램 논리에 맞지 않는 오류를 뜻한다.

ex)

나이를 입력하라고 했는데 0보다 작은 값이 입력됨.

주민등록번호 13자리만 입력하라고 했는데 중간에 - 가 삽입됨.


예외처리

예외의 상황이 되었을 때 처리하는 방법. 문제의 해결이 아닌 순수한 처리이다.


if문을 이용해서 예외를 발견하고 처리하면, 예외처리 부분과 일반적인 프로그램의 흐름을 쉽게 구분할 수 없다.

if문은 일반적인 프로그램의 논리를 구현하는데 주로 사용된다.


문법

try~catch, throw

try

{

if(예외가 발생했다면)

throw expn; //예외가 발생되면 throw가 예외발생 했다고 알려주는 개념(expn은 정보)

}

//catch가 바로 붙어야 한다. 다른 문장이 올 수 없다.

catch(type expn)

{

//예외의 처리

}

try가 expn을 받아서 catch로 던진다!!(넘겨준다)


실행 예

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
using namespace std;
 
void main(void)
{
    int num1, num2;
    cout << "두 개의 숫자 입력: ";
    cin >> num1 >> num2;
 
    try
    {
        if(num2 == 0)
            throw num2;
        
        cout << "나눗셈의 몫: " << num1/num2 << endl;
        cout << "나눗셈의 나머지: " << num1%num2 << endl;
    }
    catch(int expn)
    {
        cout << "제수는 " << expn<< "이 될 수 없습니다." << endl;
        cout << "프로그램을 다시 실행하세요" << endl;
    }
    cout << "end of main" << endl;
}
catch 블럭이 실행되면 예외가 처리된 것으로 간주된다.

예외와 연관이 있는 부분을 모두 하나의 try 블록으로 묶어야 한다!


예외가 처리되지 않으면, 예외가 발생한 함수를 호출한 영역으로 예외 데이터가(더불어 예외처리에 대한 책임까지) 전달된다.
예외처리 값은 처리가 될 때까지 넘어간다.
A->B->C->D(예외발생)  : main함수까지 넘어가고 main 함수에서 처리되지 못하면 종료되어 버린다.
예외를 처리하지 못하면 받은 함수던지 발생된 함수던지 간에 종료된다.

하나의 try블록에 다수의 catch블록이 존재할 수 있다.

전달되는 예외의 명시
int ThrowFunc(int num) throw(int, char)  //throw() <---아무런 예외도 발생하지 않는다고 명시
함수 내에서 예외상황의 발생으로 인해서 int형 예외 데이터와 char형 예외 데이터가 전달될 수 있음을 명시한 선언.
int, char 이외의 예외 데이터가 전달되면, terminate함수의 호출로 인해서 프로그램이 종료된다
프로그램의 종료는 대비하지 못한 예외상황의 처리를 알리는 의미로 받아들여진다.

객체를 예외 데이터로 던저주기(예외 객체, 예외 클래스)
예외객체 : 예외발생을 알리는데 사용되는 객체
예외클래스 : 예외객체의 생성을 위해 정의된 클래스





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

템플릿  (0) 2014.06.02
연산자 오버로딩  (0) 2014.06.02
멤버함수와 가상함수의 동작 원리  (0) 2014.06.02
static, 복사 생성자  (0) 2014.06.02
virtual 키워드와 다형성  (0) 2014.06.02
Posted by 눈떠보니내무실
,