'C++'에 해당되는 글 2건

  1. 2011.05.31 C++ _ cast 종류
  2. 2011.05.31 C++ 기본
2011.05.31 10:21

satatic_cast

C스타일의 캐스팅과 비슷하다.

용도와 제약 사항.

실수형과 정수형정수형과 열거형등의 기본 데이터 타입 간의 변환

상속관계의 클래스 계층 간의 변환

런타임 타입 검사를 하지 않음

다형성이 없어도 변환 가능 (RTTI 옵션이 꺼져있어도 된다)

다중 상속에서 기본 클래스 간의 타입 변환은 못함

 

void 포인터를 다른 타입의 포인터로 변환

 

서로 다른 타입의 포인터 간의 타입 변환은 못함

 

서로 다른 타입의 포인터 간의 타입 변환에 reinterpret_cast 를 사용하기보다는 void 포인터를 경유하는 방식을 추천한다.

dynamic_cast

dynamic_cast 는 상속 관계 안에서 포인터나 참조자의 타입을

 

기본 클래스에서 파생 클래스로의 다운 캐스팅과 다중 상속에서 기본 클래스 간의 안전한 타입 캐스팅에 사용된다.

 

안전한 타입 캐스팅이란 런타임에 타입 검사를 한다는 것이다.

- 용도와 제약 사항.

상속 관계 안에서만 사용할 수 있다.

 

하나 이상의 가상함수를 가지고 있어야 한다.

 

컴파일러의 RTTI 설정이 켜져 있어야 한다.

const_cast

const_cast 는 포인터 또는 참조형의 상수성(const)을 제거하는 데 사용된다.

 

다른 용도로는 사용하지 못하며 다른 캐스트 연산자는 상수성을 제거할 수 없다.

reinterpret_cast

캐스팅 대상을 캐스팅 타겟 타입으로 비트단위로 다시 재해석한다.

C 스타일 캐스팅과 가장 비슷하다고 보면된다.

const_cast 의 역할인 상수성을 날린다거나 하는 등의 기능은 수행하지 못한다.

- 용도와 제약 사항.

전혀 관계없는 타입 간의 변환

 

상속관계가 없는 클래스 간의 변환 포함

 

const_cast 의 기능은 수행하지 못함

  

reinterpret_cast  C 캐스팅 연산자 다음으로 위험하다.

 

캐스팅 결과는 컴파일러마다 다를 수 있다그만큼 이식성이 적다.

 

캐스팅이 자유로운 만큼 모든 책임은 프로그래머에게 돌아온다.

신고
Posted by 우엉 여왕님!! ghostkyow
2011.05.31 10:21

객체지향이란?(object-oriented-programming)

논리(함수)와 데이터가 결합된 객체가 시스템을 구성하는 것.

여기서 객체란 시스템을 구성하는 실체이며, 한 구성원의 특성과 상태변화를 구현하는 기본 단위.

 

virtual 함수

-우선! 어떤 함수에 대해서도 상속받은 기본 매개변수 값은 절대로 재정의 하면 안된다.

비가상 함수에 경우에는 어떤 이유에서건 재정의를 하면 안되기 때문에 가상함수를 상속하는 경우를 보자.

가상함수의 기본 매개변수를 재정의 하면 안되는 이유는,

가상함수는 동적으로 바인딩(지연바인딩) 되지만, 기본 매개변수 값은 정적으로 바인딩(선행바인딩) 되기 때문이다.

쉽게 말해 가상함수는 런타임시간에, 기본 매개변수는 컴파일시간에 결정된다는 것이다.

 

이러한 이유로 인해 기본 매개변수를 재정의 하면 어떤 일이 발생 하느냐!

Base *pB = new Derived();

pB->virtualFunc();

pB의 정적 타입은 Base이지만 동적 타입은 Derived가 된다. 그래서 호출되는 가상함수는 Derived의 것이 되지만

이 호출되는 가상함수에 사용되는 기본 매개변수의 값은 pB의 정적 타입 클래스에서 가져오게된다.

즉, 부모와 자식 클래스 양쪽에서 선언된 것이 섞이는 사태가 벌어진다.

 

=>이 문제를 해결하기 위해 가장 좋은 방법은 NVI관용구(비가상 인터페이스)를 쓰는것이다. 이로 인해

코드의 중복을 피할수 있고 코드 의존성까지 줄일 수 있게 된다.

 

 

 

virtual 소멸자(destructor)

-상위클래스의 소멸자가 가상이면 하위 클래스의 소멸자 역시 가상이 된다.

-생성자는 실행하는 동안 해당 객체의 동적 타입이 완전하지 않으며,

 객체를 완전히 생성하기 전에 실행 하므로 가상으로 정의 할 수 없다.

-operator=연산자를 가상으로 정의할 수는 있지만 파생클래스에 영향을 주지 못한다.

 각 클래스 별로 자신의 대입 연산자가 있기 때문이다.

 

-생성자나 소멸자를 실행하는 두 경우 객체는 아직 완전히 초기화 되지않아 불완전하므로 이를 조절하기위해 컴파일러에서는

생성 또는 소멸하는 동안 그 객체 타입이 마치 바뀐것처럼 다룬다, 즉, 파생객체를 기초객체타입인것처럼 다룬다.

-생성자나 소멸자에서는 이러한 방식으로 인해 가상함수를 호출하면 안된다. 호출된 가상함수는 해당 객체의 가상함수가 아니라

기초객체의 가상함수가 되기 때문이다.

 

 


 

복사 생성자(copy constructor)

복사생성자의 매개 변수는 꼭 const가 아니어도 되지만 참조자여야 한다.

-일반적으로 &를 사용하지않으면 컴파일차원에서 오류가 발생하는데,

 이는 참조자가 아닐경우

A(A a)

A a1;

A a2(a1); 이럴 경우

a1이 a2의 복사 생성자로 넘어가게 되면

매개변수 객체 a가 생성되고,

함수 오버로딩에 의해 복사생성자가 a객체를 인자로 받고,

또 a객체가 생성 이 상황이 반복되 무한 루프에 빠지게 된다.

그렇기 때문에 객체의 생성으로 받지않고 참조자로 받는다.

 

->그리고 보통 const를 붙여 복사생성자내에서 참조자로 받기때문에 객체의 값이 변격되는것을 막는다.

 

복사를 막기위해 복사생성자를 private로 선언한다. 그럼 이 복사생성자를 사용하려 할때 컴파일에러가 발생한다.

- 그러나 클래스의 friend와 멤버는 여전히 복사가 가능하다.

그래서 완전히 복사를 막기위해 private로 복사생성자를 선언만하고 정의를 하지 않으면 된다.

이경우 코드상에서 복사생성자를 사용하려 하면 컴파일에러가 발생.

프렌드가 사용하려하면 링크에러가 발생한다.

 

상속관계에서의 복사생성자.

-파생클래스에서 복사 생성자를 직접 정의하게되면 명시적으로 파생클래스의 복사생성자에서 기초클래스의

복사 생성자를 사용해 해당 객체의 기초 클래스 부분을 초기화 해야한다.

그렇지 않을경우 기초클래스는 기본생성자를 실행하는데,

이렇게 되면 새로 생성된 객체의 기본클래스 부분은 복사가 이루어지지 않은 원본이되고 파생클래스 부분만 복사가 이루어져

서로 다른 값을 갖게되 잠재적인 버그발생우려가 생긴다.

 

->팁으로 링크시점의 에러를 컴파일시점의 에러로 옮길 수 가있는데

이는 단순히 private에 선언되 복사생성자를 갖는 Uncopyable클래스를 하나 만들어 복사를 막을 클래스에

private상속을 시키면 된다!

 

->복사생성자를 정의하게되면 기본생성자 역시 정의해야 한다.

 

 

=>나는 지금까지는 이론적으로는 알고 있었지만 보통 복사생성자를 잘 정의해 사용하지 않았다.

하지만 일반적으로 암시적이든 명시적이든 기본 및 복사 생성자는 정의해 두는 것이 좋다.

정의 하지 않았을 경우 발생하는 대표적인 문제가 얕은복사의 예이다.

그리고 이런 기본 및 복사 생성자를 정의해 두게 되면 그 클래스의 역할이 명확해진다.

=>또한 복사생성자를 정의해야 하는 이유로는 소멸자의 중복호출로 인한 메모리누수현상이다.

//복사생성자가 없을경우

A a;

A a2 = a;

이경우 생성자는 한번 호출되고 소멸자는 두번 호출되게되어 메모리 누수가 발생한다.

이때 복사생성자를 정의해두면 복사생성자가 호출되어 메모리누수를 막을수있다.

=>이밖에 객체의 복사가 이루어질때를 대비해 복사생성자를 정의해두는 것이 좋은데, 객체가 복사되는 경우는 아래와 같다.

함수의 파라미터로 객체를 전달할때객체선언과 동시에 대입(객체를 이용한 초기화를 할때)

=>참고로 생성자내에서 동적할당을 하게 될 경우(포인터 멤버가 존재할때) 반듯이 복사생성자를 정의해 두자.

 

템플릿특수화

-빈 템플릿 매개변수 지정자(template<>)와 함수 매개변수 목록이 있어야한다.

template<>

int fnc<const char*>;  //오류! 매개변수 목록이 없다.

 

-함수 오버로딩과 템플릿 특수화

template<>를 빼면 보통의 함수선언이 된다.

오버로딩과 다른게 특수화를 하게되면 매개변수의 타입변환을 적용하지 않는다.

그러므로 특수화 버전을 사용할 경우에는 함수 매개변수 타입과 전달인자의 타입이 정확히 일치해야한다.

 

 

부분특수화

-템플릿 매개변수가 하나 이상일때 매개변수의 일부만 특수화 하는것을 말한다.

template <class T1, class T2>

class CTest{ }

//부분특수화

template <class T1>

class CTest<T1, int> { }

신고
Posted by 우엉 여왕님!! ghostkyow
TAGC++

티스토리 툴바