C++ UserDataType(구조체, 열거형, 형변환) - 24.11.18
* 형변환
- 변수나 값을 한 데이터 타입에서 다른 데이터 타입으로 변환하는 작업니다.
크게 두 가지의 형변환으로 분류할 수 있다.
1. 암시적(묵시적) 형변환
- 컴파일러가 자동으로 자료형을 반환
- 주로 작은 자료형이 큰 자료형으로 변환
- 큰 자료형을 작은 자료형으로 변환은 가능하지만, 데이터 손실이 발생할 가능성이 있다.
int a = 1;
double b = a; //int -> double 형태로 형변환 된다.
2. 명시적 형변환
- 사용자가 직접 형변환을 한다.
- C 스타일의 명시적 형변환
- 문법적으로 간단하다. 괄호 안에 원하는 데이터 타입을 명시하여 변수나 값을 반환한다.
- (target_type) value target_type -> 변환하려는 데이터 타입 value -> 변환 대상 값.
- 포인터, 기본형, 사용자 정의 타입 등 거의 모든 데이터 타입에 대해 적용이 가능하다.
- C++ 형변환 방식에 비해 어떤 변환이 이루어지는지 명확하지 않을 수 있음.
- 잘못된 형변환으로 인해 런타임 오류나 데이터 손실이 발생될 수 있다.
double dValue = 10.3;
int iValue = (int)a;
- C ++ 명시적 형변환
- 형변환을 더 안전하고 명확하기 하기 위해 캐스트 연산자를 제공한다.
- C 스타일 보다는 안정적으로 사용 가능하다.
* C++ 캐스팅 종류
1. static_cast
- 컴파일 타임에 타입을 변환하는데 사용한다. 주로 기본 타입 간의 변환에 컴파일러가 변환이 가능한지
검사하기 때문에, 잘못된 변환을 방지할 수 있다.
- UpCasting 때도 사용하기는 한다.
- 복잡한 상속 구조에서 타입 변환이 혼동을 줄 수 있을 때, 명시적으로 붙히는게 가독성에 도움이 될 수 있다.
int value = 40;
double dValue = static_cast<double>(value);
//int- > double로 명시적 형변환
2. dynamic_cast
- 상속관계에서 사용한다. 런타임에 타입 변환을 수행. 주로 DownCasting 사용.
- 안정성을 보장하여 타입이 맞지 않는다면 nullptr을 반환시킨다.
- RTTI(RunTime Type Information)을 기반으로 작동한다.
※ RTTI (RunTime Type Information) 란?
: 프로그램 실행 중에 실시간으로 데이터의 형식을 가져오는 매커니즘
런타임 중, 포인터가 가리키는 객체의 타입을 알 수 있게 해준다.
3. const_cast
: 객체의 상수성을 제거하나 추가할 때 사용한다.
타입 변환이 아닌, 상수성만 변환할 때 사용된다.
4. reinterpret_cast
: 잘 사용하지는 않는 캐스팅 종류. 매우 강력하지만 잘못 사용하게 되면 상당한 위험을 초래할 수 있음.
** 구조체
: 여러 개의 변수를 묶어, 하나의 데이터 단위로 정의하는 사용자 정의 데이터 형식.
구조체는 각각의 변수를 멤버로 가지고 이러한 멤버들은 서로 다른 데이터 타입일 수 있다.
C++에서는 함수도 포함이 가능하다.
* 형태
struct 구조체이름 { 여러 멤버 변수 } ;
struct Student
{
int age;
int phoneNumber;
string name;
void Print();
};
C++ 에서는 함수도 구조체의 멤버로 참여할 수 있다.
구조체는 선언 후 데이터 형식으로 변수를 생성해 사용할 수 있다.
{ } 를 이용해, 멤버 변수를 순서대로 초기화할 수 있다.
구조체 내 멤버 변수에게 접근하기 위해서는 . 연산자를 사용하여 접근한다.
struct Student
{
int age;
int phoneNumber;
string name;
void Print();
};
int main()
{
Student st;
st = { 17, 2356, "학생1" };
cout<<st.name << "의 나이는 " <<st.age<<"살 입니다."<<endl;
//결과 : 학생1의 나이는 17살 입니다.
}
§ 두 점 사이의 거리를 계산하는 함수
struct Point
{
int x;
int y;
};
double CalculateDistance(const Point& p1, cont Point& p2)
{
double deltaX = p2.x - p1.x;
double deltaY = p2.y - p1.y;
return sqrt((deltaX*delta) + (deltaY * deltaY));
}
* sqrt는 제공된 값에 루트를 씌워 반환한다. sqrt(9) -> 루트9 -> 3이 반환된다
* 열거형
- 상수 집합에 이름을 붙여서 사용하는 데이터 타입
- 코드의 가독성을 높일 수 있다.
- 기본적으로 int 타입으로 처리되며, 자동으로 첫 번째 값이 0부터 시작하여 1씩 증가합니다.
- 명시적으로 값을 지정할 수 있다.
열거형(enum)의 형태
enum 열거형 이름 { } ;
enum Color
{
// 0, 1, 2
Red,Green,Black
};
열거형 내에 멤버들에게 접근하기 위해서는 범위 지정 연산자 ( :: ) 를 사용해야 한다.
cout<<Color::Red<<endl; //0
* enum vs enum class
- enum 은 서로 다른 enum 들과 멤버의 이름이 중복되어서는 안되지만,
enum class 에서는 서로 다른 객체 사이에서도 멤버 이름이 중복될 수 있다.
- enum 은 특정 멤버를 따로 선언 및 초기화하지 않고 사용가능하기 때문에, 오류가 발생하거나 불분명한 값을 가지게 될 수도 있다.
enum class는 class 라는 타입이 생겼기때문에 소속이 명확하고, 그에 따라 자신의 범위를 지정해주어야 한다.
- enum은 묵시적으로 해당 값들을 int형의 정수로 변환시켜 비교 연산이 가능하지만, enum class는 형변환을 하지 않는 이상 서로 다른 enum class 타입끼리 비교할 수 없다.
enum Color
{
Red, Green, Black
};
enum class Location
{
lnven,
Town,
Shop
};
int main()
{
Color c = Red;
Location l = Location::Town; //범위를 명확하게 지정해주어야 한다.
if(c == 1)
{
cout<<"Red 는 1이다."<<endl; //enum은 비교가 가능하다.
}
}
문자열 함수 (str- )
※ 대표적인 무자열 관련 함수들
- strlen(const char* str) : 문자열의 길이를 반환한다.
- strcpy(char* dest, const char* src) : 문자열 src를 dest에 복사하여 넣는다.( copy )
- strcat(char* dest, const char* src) : src를 dest 문자열 끝에 이어 붙인다. 문자열 연결.
- strcmp(const char* str1, const char* str2) : str1 과 str2 문자열을 비교한다.
ㄴ 동일하면 0 반환. str1 이 str2 보다 작으면 음수, 크면 양수를 반환한다.
const char* str = "Hello";
char str1[10] = "abcd"
cout<<strlen(str); //5
cout<<strlen(str1); //4
const char* cmp1 = "aab" //아스키코드 -> 97 97 98
const char* cmp2 = "aac" //아스키코드 -> 97 97 99
cout<<strcmp(cmp1, cmp2); // cmp1이 더 작기 때문에 음수(-1) 반환
char cpy1[10] = "hi,";
char cpy2[10] = "Tom."; //복사해 넣을 배열의 크기는 복사할 내용의 배열보다 크기가 커야한다.
//문자열 배열 끝에는 null값도 있기 때문에, null값도 고려해야한다.
strcpy_s(cpy2, cpy1); //cpy2에 cpy1을 복사하여 넣는다.
cout<<cpy2; //hi, 출력
char s1[10] = "Mr.M";
char s2[20] = "Hi, ";
strcat_s(s2,s1); // s2에 s1을 이어 붙인다.
cout<<s2<<endl; // Hi, Mr.M
§ 문자열 뒤집기 함수
void ReverseStr(char str[])
{
int len = strlen(str);
char temp;
for(int i = 0; i < len/2;i++) //문자열의 절반까지만 반복
{
temp = str[i];
str[i] = str[len-i-1]; //문자열의 뒤쪽 부터 앞으로 넣어준다
str[len-i-1] = temp;
}
}