[C++](번역)형변환(1) - 묵시적,명시적 형변환

김형태·2021년 5월 13일
0

C++

목록 보기
12/13
post-custom-banner

1. Implicit conversion(묵시적 변환)

Implicit conversions are automatically performed when a value is copied to a compatible type. For example:

묵시적 변환은 값이 호환되는 형식으로 복사될 때 자동으로 수행된다. 예를 들어

short a=2000;
int b;
b=a;

Here, the value of a is promoted from short to int without the need of any explicit operator. This is known as a standard conversion. Standard conversions affect fundamental data types, and allow the conversions between numerical types (short to int, int to float, double to int...), to or from bool, and some pointer conversions.

여기서 a의 값은 명시적인 연산자 없이 short에서 int로 프로모션된다. 이를 표준 변환(standard conversion)이라고 한다. 표준 변환은 기본 데이터 유형에 영향을 미치며 숫자 유형(int에서 float, double에서 float...)간의 변환, bool에서 숫자 혹은 숫자에서 bool 및 일부 포인터 변환 간의 변환을 허용한다.

Converting to int from some smaller integer type, or to double from float is known as promotion, and is guaranteed to produce the exact same value in the destination type. Other conversions between arithmetic types may not always be able to represent the same value exactly:

  • If a negative integer value is converted to an unsigned type, the resulting value corresponds to its 2's complement bitwise representation (i.e., -1 becomes the largest value representable by the type, -2 the second largest, ...).
  • The conversions from/to bool consider false equivalent to zero (for numeric types) and to null pointer (for pointer types); true is equivalent to all other values and is converted to the equivalent of 1.
  • If the conversion is from a floating-point type to an integer type, the value is truncated (the decimal part is removed). If the result lies outside the range of representable values by the type, the conversion causes undefined behavior.
  • Otherwise, if the conversion is between numeric types of the same kind (integer-to-integer or floating-to-floating), the conversion is valid, but the value is implementation-specific (and may not be portable).

더 작은 정수 유형에서 int로 변환하거나 float에서 double로 변환하는 것을 프로모션이라고 하며, 대상 유형에서 정확히 동일한 값을 생성하도록 보장한다. 산술 유형(arithmetic type)간의 다른 변환은 항상 동일한 값을 정확하게 나타내지 못할 수 있다.

  • 음의 정수 값이 부호 없는 형식으로 변환되는 경우, 결과 값은 2의 보완 비트 표현에 해당된다(즉, -1은 유형으로 나타낼 수 있는 가장 큰 값이 되고 -2는 두 번째로 큰.../int i = -1;unsigned int로 형변환 하면 4294967295).
  • bool로 혹은 bool로부터의 변환은 false를 0(숫자 유형의 경우)과 Null 포인터(포인터 유형의 경우)로 간주한다. true는 다른 모든 값과 동일하며 1과 동등하게 변환된다.
  • 부동 소수점 유형에서 정수 유형으로 변환하는 경우 값이 잘린다(소수 부분이 제거됨). 결과가 유형별로 나타낼 수 있는 값의 범위를 벗어나는 경우 변환은 정의되지 않은 동작을 일으킨다.
  • 그렇지 않은 경우 변환이 동일한 종류의 숫자 유형(정수 대 정수 또는 부동 대 부동) 사이에 있는 경우 변환은 유효하지만 값은 구현에 따라 다르다.

Some of these conversions may imply a loss of precision, which the compiler can signal with a warning. This warning can be avoided with an explicit conversion.

이러한 변환 중 일부는 컴파일러가 경고 신호를 보낼 수 있는 정밀도의 상실을 의미할 수 있다. 이 경고는 명시적 변환으로 방지할 수 있다.

For non-fundamental types, arrays and functions implicitly convert to pointers, and pointers in general allow the following conversions:

  • Null pointers can be converted to pointers of any type
  • Pointers to any type can be converted to void pointers.
  • Pointer upcast: pointers to a derived class can be converted to a pointer of an accessible and unambiguous base class, without modifying its const or volatile qualification.

기본이 아닌 유형의 경우, 배열과 함수는 묵시적으로 포인터로 변환되며 포인터는 일반적으로 다음과 같은 변환을 허용한다.

  • Null 포인터를 모든 유형의 포인터로 변환할 수 있다.
  • 모든 유형의 포인터는 void 포인터로 변환할 수 있다.
  • 포인터 업 캐스트 : 유도 클래스에 대한 포인터는 const 또는 volatile qualification을 수정하지 않고(?) 액세스 가능하고 모호하지 않은 기본 클래스의 포인터로 변환 될 수 있다.(??)

2. Implicit conversions with classes(클래스의 묵시적 변환)

In the world of classes, implicit conversions can be controlled by means of three member functions:

  • Single-argument constructors: allow implicit conversion from a particular type to initialize an object.
  • Assignment operator: allow implicit conversion from a particular type on assignments.
  • Type-cast operator: allow implicit conversion to a particular type.

클래스의 세계에서 묵시적 변환은 다음 세 가지 멤버 함수를 사용하여 제어할 수 있다.

  • 단일 인자 생성자: 특정 유형에서 개체를 초기화하도록 묵시적 변환을 허용한다.
  • 할당 연산자: 특정 유형의 할당을 묵시적으로 변환하도록 허용한다.
  • 형-변환 연산자: 특정 유형으로 암묵적으로 변환하도록 허용한다.

예시:

// implicit conversion of classes:
#include <iostream>
using namespace std;

class A {};

class B {
public:
  // conversion from A (constructor):
  B (const A& x) {}
  // conversion from A (assignment):
  B& operator= (const A& x) {return *this;}
  // conversion to A (type-cast operator)
  operator A() {return A();}
};

int main ()
{
  A foo;
  B bar = foo;    // calls constructor
  bar = foo;      // calls assignment
  foo = bar;      // calls type-cast operator
  return 0;
}

The type-cast operator uses a particular syntax: it uses the operator keyword followed by the destination type and an empty set of parentheses. Notice that the return type is the destination type and thus is not specified before the operator keyword.

type-cast 연산자는 연산자 키워드 뒤에 대상 유형 및 빈 괄호 집합을 사용한다. 반환 유형이 대상 유형이기 때문에 연산자 키워드 앞에 지정되지 않는다.


3. Keyword explicit(explicit 키워드)

On a function call, C++ allows one implicit conversion to happen for each argument. This may be somewhat problematic for classes, because it is not always what is intended. For example, if we add the following function to the last example:

함수 호출에서 C++는 각 인수에 대해 하나의 묵시적 변환을 허용한다. 이것은 의도된 대로만 작동하진 않기 때문에 클래스에 다소 문제가 있을 수 있다. 예를 들어 마지막 예제에 다음 기능을 추가하는 경우:

void fn (B arg) {}

This function takes an argument of type B, but it could as well be called with an object of type A as argument:

이 함수는 B 유형의 인수를 사용하지만 A 유형의 개체와 함께 다음과 같이 호출할 수 있다.

fn (foo);

This may or may not be what was intended. But, in any case, it can be prevented by marking the affected constructor with the explicit keyword:

이것은 의도 한 것일 수도 있고 아닐 수도 있다. 그러나 어쨌든 영향을 받는 생성자를 명시적 키워드로 표시하여 방지할 수 있다.

// explicit:
#include <iostream>
using namespace std;

class A {};

class B {
public:
  explicit B (const A& x) {}
  B& operator= (const A& x) {return *this;}
  operator A() {return A();}
};

void fn (B x) {}

int main ()
{
  A foo;
  B bar (foo);
  bar = foo;
  foo = bar;
  
//  fn (foo);  // not allowed for explicit ctor.
  fn (bar);  

  return 0;
}

Additionally, constructors marked with explicit cannot be called with the assignment-like syntax; In the above example, bar could not have been constructed with:

또한 명시적 구문으로 표시된 생성자를 할당과 같은 구문으로 호출할 수 없습니다. 위의 예에서는 bar를 다음과 같이 구성할 수 없습니다.

B bar = foo;

Type-cast member functions (those described in the previous section) can also be specified as explicit. This prevents implicit conversions in the same way as explicit-specified constructors do for the destination type.

타입-캐스트 멤버 함수(이전 섹션에서 설명한 함수)도 명시적인 것으로 지정할 수 있습니다. 이렇게 하면 명시적으로 지정된 생성자가 대상 유형에 대해 수행하는 것과 같은 방식으로 암시적 변환을 방지할 수 있습니다.

profile
steady
post-custom-banner

0개의 댓글