2008-11-15 3 views
3
내가 2005 년

는 왜이 법률, C++ 형식 정의 FUNC

typedef void (*cleanup_t)(); 

void func(cleanup_t clean) 
{ 
    cleanup_t(); 
} 

MSVC에서이 왜이 컴파일 않습니다 않았다

? 나에게 경고하지 마라. 알았어, 그것은 나에게 참조되지 않은 형식 매개 변수 경고를 주었지 만, 원래이 클래스는 깨끗하지 않았을 때 이것을했다.이 코드가 문제를 일으켰을 때 참조되지 않은 형식 매개 변수가 없었다.

cleanup_t()는 무엇입니까? 정말로하고 있고 요점은 무엇입니까? 웃음을 위해 나는 int()를 시도했고 그것은 또한 효과가 있었다.

답변

9

해당 유형의 임시을 만들 수 cleanup_t 유형에 대한 기본 초기화를 실행하고 결코 실제로 일시적인 것을 사용하고.

"MyClass c = MyClass();"의 "MyClass()"부분과 비슷하지만 포인터에 함수 유형에는 실제로 생성자가 없습니다. 물론 내 코드 단편에서 "MyClass()"는 이니셜 라이저 표현식이므로 반드시 임시로 만들 필요는 없습니다. "MyClass(). some_method();"의 "MyClass()" 아마 더 가까운 유추 일 것입니다.

"int()"는 "int (0)"을 말하는 또 다른 방법으로 "0"을 말하는 또 다른 방법 인 "(int) 0"을 말하는 또 다른 방법입니다. 다시 말하지만, 임시에 할당하고, 전체 문장이면 임시는 사용되지 않습니다.

GCC에서 -Wall을 사용하여 질문의 코드를 컴파일하면 "명령문은 아무 효과가 없습니다"라는 경고 메시지가 나타납니다. 이 작업을 수행하는 사람이 "clean();"을 입력하면 함수를 호출하는 효과가 있기 때문에 해당 경고가 생성되지 않습니다. 경고를 켜고 올바르게 수정해야하는 또 다른 이유는 다음과 같습니다.

12

저는 이것이 cleanup_t 유형에 대한 기본값으로 평가되는 표현식이라고 생각합니다. 즉, void를 반환하는 함수에 NULL 포인터를 반환하는 식입니다. - (이것이 내가 생각하는) C/C++, 부작용과 표현에서

는이 같은 진술 할 수처럼 유효 문은 다음과 같습니다 구문 오류가 아니다

1 + 2; 

을하지만, 일부 컴파일러는 경고를 줄 수 있습니다. 이러한 유형의 표현식은 매크로 (assert() 매크로와 같은)를 디버깅 목적으로 자주 사용하기 때문에 NULL 값을 반환하는 부작용이없는 표현식에 대한 경고를 제공하지 않습니다.

cleanup_t 유형의 기본 생성자를 호출하는 것으로 생각할 수 있습니다. 기본 형식 (또는 typedef)에 대한이 기본 생성자와 유사한 구문을 C++에 추가하여 템플릿에서 템플릿 매개 변수로 전달 된 형식의 항목을 기본값으로 설정하면서 템플릿 형식 매개 변수를 기본 형식으로 설정할 수 있도록했습니다 비 사용자 정의 유형. 다른 이유가있을 수 있지만 그 중 하나라고 생각합니다. 같은

뭔가 :

template <class T> 
class foo 
{ 
    T myT; 

    public: 

    foo() { 
     myT = T(); 
    }; 
}; 

typedef void (*cleanup_t)(); 


class bar 
{ 
}; 


int not_quite_a_cleanup_t_func() 
{ 
    return 1; 
} 


int main() 
{ 
    foo<int> intFoo; 
    foo<cleanup_t> cleanup_t_foo; 
    foo<bar> barFoo; 

    // here I'm going to harp on one of the things I don't like about C++: 
    // 
    // That so many things that look like function calls are not or that 
    // the parens cause subtle behavior changes. 
    // 
    // I believe this is the reason this question was posted to 
    // stackoverflow, so it's not too far off topic. 
    // 
    // Many of these things exist because of backwards compatibility with C or 
    // because they wanted to fit in new features without adding keywords or 
    // new reserved tokens or making the parser even more complex than it already 
    // is. So there are probably good rationales for them. 
    // 
    // But I find it confusing more often than not, and the fact that there 
    // might be a rationale for it doesn't mean I have to like it... 

    cleanup_t cleanup1(); // declares a function named cleanup1 that returns a cleanup_t 

    cleanup_t cleanup2 = cleanup_t(); // cleanup2 is a variable of type cleanup_t that 
             // is default initialized 

    cleanup_t* cleanup3 = new cleanup_t; // cleanup3 is a pointer to type cleanup_t that 
              // is initialized to point to memory that is 
              // *not* initialized 

    cleanup_t* cleanup4 = new cleanup_t(); // cleanup4 is a pointer to type cleanup_t that 
              // is initialized to point to memory that *is* 
              // initialized (using default intialization) 

    cleanup2 = cleanup_t(not_quite_a_cleanup_t_func); // explicit type conversion using functional notation 

    cleanup_t(); // the OP's problem 
    cleanup2();  // call the function pointed to by cleanup2 
    (*cleanup2)(); // same thing 

    class cleanup_class 
    { 
     cleanup_t cleanup5; 

    public: 
     cleanup_class() : 
      cleanup5() // class member default initialization 
     { }; 
    }; 
}