2015-01-07 1 views
1

스탠리 리프만의 "C++ 프라이머는"페이지 (234)에서,이 의미는 함수의 몸체 내부에 함수를 선언, 그렇게 할 수있는 상황 그럼에도 불구하고C++ : 다른 함수 내에서 함수를 선언하는 용도는 무엇입니까?

Ordinarily, it is a bad idea to declare a function locally. However, to explain how scope interacts with overloading, we will violate this practice and use local function declarations.

... 
void print(const string &); 
void print(double); // overloads the print function 
void fooBar(int ival) 
{ ... 
    // bad practice: usually it's a bad idea to declare functions at local scope 
    void print(int); // new scope: hides previous instances of print 
    print(ival); // ok: print(int) is visible 
    print(3.14); // ok: calls print(int); print(double) is hidden 
} 

, 언급?

나는 계획에 유사한 코드를 기억 :

(define (PowerSet set) 
    (if (null? set) '(()) 
     (let ((PowerSetAfterHead (PowerSet (cdr set)))) 
     (append PowerSetAfterHead 
      (PowerSet (cdr set)) 
      (map 
       (lambda (subset) 
        (cons (car set) subset 
       ) 
       ) 
       (PowerSet (cdr set))         
      ) 
     ) 
    ) 
    ) 
) 

는 일반적으로 외부 함수의 사용만을위한 의도 "로컬 기능"의 오용 숨기는 데 사용되어 있습니까? 내부 수업 같은 거요? 또는 일부 디자인 패턴에서 유용합니까?

+0

"일반적으로 함수를 로컬로 선언하는 것은 좋지 않습니다." ;) –

+0

특정 오버로드를 제외하고 모두 명시 적으로 숨기려면? –

+0

캐스트를 사용하여 명시 적으로 선택하는 것이 더 좋은 생각 일 수도 있지만 ... – Deduplicator

답변

2

함수를 호출 할 때 모호한 부분이있을 때 문제가 발생합니다. 따라서 어떤 범위에서 모호성을 피하기 위해 외부 함수의 동일한 이름을 가진 다른 모든 함수를 숨기는 필수 함수를 다시 선언 할 수 있습니다.

다음의 간단한 예를 고려하십시오. 10 : 9 : 오류 : 다음 프로그램을 실행하면

#include <iostream> 

void f(int) { std::cout << "f(int)" << std::endl; } 
void f(double) { std::cout << "f(double)" << std::endl; } 

int main() 
{ 
    f(10l); 

    return 0; 
} 

당신은

prog.cpp 같은 오류가 발생합니다 과부하 'F (긴 INT)'의 호출이 모호 F (10리터); 당신이 코드를 컴파일합니다이

#include <iostream> 

void f(int) { std::cout << "f(int)" << std::endl; } 
void f(double) { std::cout << "f(double)" << std::endl; } 

int main() 
{ 
    void f(double); 
    f(10l); 

    return 0; 
} 

같은 주 내에서 f를 함수의 선언을 추가하고 출력이

f(double) 
+0

나는 그것을 얻지 못합니다. 이 샘플에서 내부적으로 선언 된 함수'print (int);는 실제로 외부의 모든 것을 숨 깁니다. B'print (const string &);와 C'print (double); 그래서 여전히 A를 정의 할 필요가 있습니다. A와 B가 선언 된 A와 B가 내부적으로 A를 다시 선언하더라도 A를 다시 정의해야합니다. 절약 할 수 없습니다. – athos

+0

@athos 나는 당신이 말한 것을 이해하지 못했습니다. 로컬 함수 선언이 유용한 이유를 보여주는 유사한 예제가 있습니다. –

+0

@vlad_from_moscow 감사합니다. 이제 알았으니'f (double)'는'main()'을 사용하면 다시 정의 할 필요가 없다. – athos

2

당신의 체계의 예처럼 보일 것입니다 경우

그러나 모두는 선언과 정의 지역 함수.

C++ 예제는 함수를 로컬에서 선언합니다.

다른 것들입니다.

C++ 11에서 lambdas를 사용하여 구성표 로컬 함수와 비슷한 기능을 만들 수 있습니다.

기능을 로컬로 선언하면 "이 이름과 서명의 기능이 있습니다"라는 메시지 만 나타납니다. 함수 밖의 것보다 더 좁은 범위에서 더 그렇다. 그리고 더 좁은 범위의 함수 만이 오버로드 (더 넓은 범위의 함수가 아닌)로 간주된다.

새 기능이 만들어지지 않습니다.이 기능은 다른 곳에서 정의해야합니다. (로컬 클래스 메서드와 람다와 같은 것을 제외하면 C++에서 로컬 함수를 정의 할 수 없습니다.)

과부하 해결 방법을 변경하는 데이 방법을 사용할 수는 있지만 거의 권장되지 않습니다. 오버로드가 모호한 경우 수동으로 형식을 변환 한 다음 오버로드 집합을 호출하고 정상적으로 해결하는 것이 좋습니다.

다른 대안은 호출 할 오버로드 만 선언 한 다음 호출하는 것입니다.이렇게하면 놀라운 결과가 발생할 수 있으므로 가능한 경우 매우 좁은 범위에서만 그렇게하십시오. 왜 그렇게하는지, 발생할 수있는 문제를 문서화하십시오 (소수의 프로그래머가 범위 숨기기 오버로드 규칙을 자신의 앞에 놓을 것입니다. 적어도 약간의 자극없이 코드를 읽을 때 두뇌).

필자는 로컬 함수를 선언해야하는 상황에 직면 해본 적이 없다고 생각합니다.

내가 진흙 코드의 진지한 공을 해킹하고 프로토 타입/디버깅 목적으로 극도의 로컬 변경을하고 싶었 기 때문에 나는 그랬다. 간단히 함수 서명을 선언하고 어딘가에 호출했습니다. 이 함수는 다른 곳의 같은 라이브러리에있는 다른 .cpp 파일의 정적 로컬입니다. 거기서 정적을 제거하고 호출 한 결과를 테스트했습니다.

이 파일은 헤더 파일을 생성하거나 저장하는 등의 방법으로 헤더 파일을 생성하여 저장합니다. 생산에 전념하기 전에 나는 그와 같은 단계를 밟을 것이다 (그리고 내가 그곳에있는 동안 정적 로컬 함수의 인터페이스를 정리할 것이다).

그래서 빠르고 간단한 프로토 타입 해킹에 사용했습니다. 마지막으로이 작업을 수행 할 때 프로토 타입 해킹을 수행 한 후에 되돌리기로 끝났습니다.이 작업은 한 곳에서 각각 2 개의 파일 만 터치했기 때문에 쉽습니다.

+0

감사합니다! 이제 차이점을 이해합니다. – athos

관련 문제