char*과 string 간의 전환

pool007의 이미지

throw 에서 " " 로 둘러싸인 문자열을 던질때 왜 이것이
const string 으로 잡히지 않는지요..

#include <iostream>

using namespace std;

int main(void)
{
  try
    {
      throw "message";
    }

  catch (const string& s)
    {
      cerr << "string: " << s << endl;
    }

  catch (const char* s)
    {
      cerr << "char*: " << s << endl;
    }

  return EXIT_SUCCESS;
}

이 코드에서 const string& 쪽에서 잡히지가 않네요..
char * 이라면 던져지면서 그것이 자동으로 conversion 되거나
하지 않나요?

이렇게 2개의 string을 위한 처리를 따로 해야하는 것인지 궁금합니다.

doldori의 이미지

throw 되는 개체를 받을 수 있는 catch 블럭은 다음 4가지 중 하나일 때입니다.

void f() 
{ 
    try { 
        throw E() ; 
    } 
    catch (H) { 
        // when do we get here? 
    } 
} 

1. H와 E가 같은 형일 때
2. H가 E의 public 기초 클래스일 때
3. H와 E가 모두 포인터형이고 그것들이 가리키는 개체간의 관계가 1이나 2일 때
4. H가 참조형이고 H가 참조하는 개체와 E의 관계가 1이나 2일 때

따라서 const char* 예외를 const string으로 받을 수는 없습니다. string으로
받으려면 throw string("message") 로 해야 합니다.

pool007의 이미지

#include <iostream>

using namespace std;

void foo (const string s)
{
  cout << s << endl;
}

int main(void)
{
  foo("hi");
  return EXIT_SUCCESS;
}

이 프로그램은 "hi"를 제대로 출력합니다.

그렇다면 이렇게 봐도 될런지요?

Quote:

" " 로 묶인 문자열은 const char* 이며, 필요하면 string으로 변환이
되지만 try-catch에서만은 예외이다.

--
Passion is like genius; a miracle.

doldori의 이미지

"예외를 던질 때는 예외"라... 재미있는 말이군요. :)
이런 식으로 이해를 해본 적은 없는데...
자연어가 아닌 프로그래밍 언어 규칙은 매우 엄밀하게 정의가 되기 때문에
규칙에 예외를 둔다고 보는 것은 좀 이상하지 않을까 합니다. (물론 나중에
규칙 자체에 결함이 발견되어 개정을 하는 경우는 있습니다만.)
그냥 throw-catch의 규칙은 그렇다고 보는 것이 좋을 것 같습니다.

mr.lee의 이미지

Quote:
" " 로 묶인 문자열은 const char* 이며, 필요하면 string으로 변환이
되지만 try-catch에서만은 예외이다.

이 표현은 적절치 않는것 같습니다.

함수(메소드) 호출시 인자로 들어가는 타입은 인자로 받는 클래스의 생성자의 인자로 들어갈 수 있습니다. 이것은 묵시적 형변환 이라고도 하는데 대입시의 그것과 같은 상황이지요.

위에서 string의 생성자중 const char* 를 받는게 없다면 에러가 나겠지요. 때론 이러한것을 방지할 필요가 있을땐 explicit 예약어를 사용하여 명시적인 생성만 받아들이게 합니다.

묵시적형변환

#include <iostream>

using namespace std;

class T {
public:
   T(int a) {
      cout << a << endl;
   }
};

void test(T t) {}

int main() {
   test(5);
   T a = 5;
   return 0;
}

명시적형변환

#include <iostream>

using namespace std;

class T {
public:
   explicit T(int a) {
      cout << a << endl;
   }
};

void test(T t) {}

int main() {
   test(5); // 에러
   T a = 5; // 에러
   return 0;
}

설명중 용어사용이 조금 부정확했을수도 있습니다. 잘못된 부분이 있다면 다른분께서 수정해 주시기 바랍니다.