2015-02-06 4 views
5

현재 FLTK GUI 라이브러리를 실험 중이지만 콜백 함수가 무엇이 진행되고 있는지 확실히 알 수는 없습니다. — 구체적으로 타입 캐스팅 물건은 제게는 외계인입니다. 아래의 예는 "Press"라고 표시된 버튼이있는 기본 창을 보여줍니다. 버튼을 누르면 라벨이 "완료"로 바뀝니다. 콜백 함수에 전달타입 캐스팅/콜백 타입

레이블 유형 const char*로 선언 후는 void*를 입력 캐스팅, 그러나 그것은 std::string로 선언하는 것이 가능하고 void* 캐스팅? 나는 현대의 C++ 문자열을 char 표기법보다 선호한다.

또한 아래 유형을 다른 유형으로 변환하는 가장 좋은 방법은 무엇입니까? 나는 static_cast<type>()이 전에 사용 된 것을 보았습니다 만, const char*에서 void* 또는 그 반대로 캐스트를 수행하는 가장 안전한 방법은 무엇입니까? C++ 11은 무엇을 추천할까요?

#include <FL/Fl.H> 
#include <FL/Fl_Window.H> 
#include <FL/Fl_Button.H> 
#include <FL/Fl_Native_File_Chooser.H> 
#include <string> 

void xyz_callback(Fl_Widget* w, void* userdata) 
{ 

    Fl_Button* b = (Fl_Button*)w; //cast widget w to button and assign to b 

    b->label((const char*)userdata); //cast userdata back to type const char* 
} 


int main(int argc, char **argv) 
{ 
    Fl_Window *window = new Fl_Window(340,180); 
    Fl_Button *button = new Fl_Button(20,40,300,100, "label"); 
    button->label("Press"); 
    button->labelfont(FL_BOLD+FL_ITALIC); 
    button->labelsize(36); 
    button->labeltype(FL_SHADOW_LABEL); 
    button->when(FL_WHEN_RELEASE); 

    const char* word = "Done"; 
    button->callback(xyz_callback, (void*)word); //cast word to type void* 

    window->end(); 
    window->show(argc, argv); 
    return Fl::run(); 
} 
+0

을하지만, 그것은 표준 : : 문자열로 선언 할 수 있습니다 다음에 "무효 *"주연 : 당신이 그런 식으로 할 경우

코드는 다음과 같이 것인가? 네. –

+1

@BartekBanachewicz std :: string 또는 std :: string에 대한 포인터를 캐스팅 하시겠습니까? – harper

+0

글쎄, 그것에 대한 포인터. –

답변

6

(T)a 스타일 캐스팅, 또한 C 스타일의 캐스팅으로 알려져, 실제로는 최악의 방법 C++에서 명시 적 변환을 수행합니다. 그것은 가장 강력한 —이기 때문에 행복하게 거의 모든 것을 변환하여 심각한 오류를 쉽게 숨길 수 있습니다. 이것은 C에서 사용할 수있는 명시적인 타입 변환의 유일한 형태이며, C++에 의해 그대로 상속되었지만 결코 고품질의 C++ 코드에서 사용되어서는 안됩니다.

void*word의 캐스팅은 — 오브젝트 유형 어떤 포인터 불필요한 암시 void에 대한 포인터로 변환 할 수 있습니다.

콜백에서 const char*으로 캐스트 백해야하지만 static_cast<const char*>(userdata)으로 수행 할 수 있습니다.

std::string에 대한 질문을 해결하려면 : 평생에 따라 다릅니다. std::string*void*으로 변환하여 콜백으로 전달할 수 있습니다. 거기에 str::string*으로 캐스팅 한 다음 c_str()을 검색하여 label 함수로 전달합니다. 그러나 콜백이 호출 될 때까지 std::string이 가리키고 있는지 확인해야합니다 (범위를 벗어나지 않았습니다). main의 로컬 변수로 만들면 꽤 안전합니다.

void xyz_callback(Fl_Widget* w, void* userdata) 
{ 
    Fl_Button* b = static_cast<Fl_Button*>(w); 

    b->label(static_cast<std::string*>(userdata)->c_str()); 
} 


int main(int argc, char **argv) 
{ 
    Fl_Window *window = new Fl_Window(340,180); 
    Fl_Button *button = new Fl_Button(20,40,300,100, "label"); 
    button->label("Press"); 
    button->labelfont(FL_BOLD+FL_ITALIC); 
    button->labelsize(36); 
    button->labeltype(FL_SHADOW_LABEL); 
    button->when(FL_WHEN_RELEASE); 

    std::string word = "Done"; 
    button->callback(xyz_callback, &word); 

    window->end(); 
    window->show(argc, argv); 
    return Fl::run(); 
} 
+0

많은 분들에게 감사드립니다. Angew - 그건 내 머리 속에있는 몇 가지 것들을 명확히하는 데 필요한 정보 유형이며, 제안한 코드를 사용하면 더욱 행복해집니다. 회신에 시간을내어 주셔서 감사합니다! –

+0

@EdwardJeckyll 답변으로 문제가 해결되면 * 수락 (* 옆의 초록색 체크 표시를 클릭하여 질문 당 최대 하나의 답을 허용)으로 마킹하는 것이 좋습니다. 이것은 해결 된 것으로 표시하고 응답자와 당신에게 약간의 평판을줍니다. 그것은 [스택 오버플로 방식으로 "감사합니다."(http://stackoverflow.com/help/someone-answers)입니다. – Angew

+0

감사합니다, Angew. –

0

콜백 아무것도에 대한 포인터를 전달할 수 있습니다 당신보다 void*를 기대합니다. 그러나 콜백은 인수를 처리하는 방법을 알아야합니다. 다시 사용 가능한 유형으로 변환해야합니다.

std::string에 포인터가 올 수 있도록 콜백을 변경할 수 있습니다. 당신은 콜백에서 const char*를 원한다면 당신이 콜백에 C 스타일 문자열을 전달해야한다 :

button->callback(xyz_callback, str.c_str()); 
+0

마이너스 1 - 누군가에게'c_str()'을 사용하도록 말하고 평생 관리 문제는 기술하지 않는다. 콜백. 위의 질문 코드에 코드를 드롭하면 끔찍한 일이 일어날 것입니다. – Yakk

+0

@Yakk 콜백은 동 기적으로 호출됩니다. 콜백은 어쨌든 데이터의 소유권을 가져야합니다. 포인터를 로컬 변수에 전달하는 것과 같은 문제가 있습니다. 그러나 이것은 질문의 일부가 아닙니다. 여기서 프로그래밍 스타일의 책을 읽을 수는 없습니다. – harper

+0

좋은 점 -'main'이 끝나기 전에':: run()'을합니다. – Yakk