중첩 된 기능은 허용되지 않지만 왜 중첩 된 기능 프로토 타입이 허용됩니까? [C ++

StackOverflow https://stackoverflow.com/questions/928992

문제

나는 ~였다 독서 연결된 질문은이 질문을하게합니다.

다음 코드를 고려하십시오

int main()
{
    string SomeString();
}

모두, 컴파일러는 이것을 기능 프로토 타입으로 간주하고 물체. 이제 다음 코드를 고려하십시오.

int main()
{
    string Some()
    {
        return "";
    }
}

컴파일러는 이것이 중첩 된 기능 정의가 허용되지 않는다고 생각하기 때문에 유효하지 않다고 말했다. 허용되지 않으면 중첩 된 기능 프로토 타입이 허용되는 이유는 무엇입니까? 혼란을 일으키는 것이 아니라 유리한 점을 제시하지 않습니다 (또는 여기에 몇 가지 유효한 포인트가 없습니까?).

다음이 유효하다는 것을 알아 냈습니다.

int main()
{ 
  string SomeFun();
  SomeFun();
  return 0;
}

string SomeFun()
{
  std::cout << "WOW this is unexpected" << std::endl;
}

이것은 또한 혼란 스럽습니다. 나는 그 기능을 기대하고 있었다 somefun () 범위 만 있으면됩니다 기본. 그러나 나는 틀렸다. 컴파일러가 위와 같이 코드를 컴파일 할 수있는 이유는 무엇입니까? 위의 코드와 같은 코드가 의미가있는 실시간 상황이 있습니까?

이견있는 사람?

도움이 되었습니까?

해결책

당신의 프로토 타입은 단지 '선언 선언'. Wikipedia 기사를 확인하십시오.

기본적으로 컴파일러를 알려줍니다 " 'NodyFun'라벨이 이런 식으로 사용되면 놀라지 마십시오." 그러나 링커는 올바른 기능 본문을 찾는 데 책임이 있습니다.

실제로 가짜 프로토 타입 (예 : 'char somefun ()'를 선언하고 메인 전체에 사용할 수 있습니다. 링커가 가짜 기능의 본문을 찾으려고 할 때만 오류가 발생합니다. 그러나 컴파일러는 시원합니다.

많은 이점이 있습니다. 기능 본문이 항상 동일한 소스 코드 파일에 있다는 것을 기억해야합니다. 링크 된 라이브러리에있을 수 있습니다. 또한 링크 된 라이브러리는 특정 '링크 서명'이있을 수 있습니다. 조건부 정의는 스코어 된 프로토 타입을 사용하여 빌드 시간에 올바른 링크 서명을 선택할 수도 있습니다. 대신.

도움이 되었기를 바랍니다.

다른 팁

C ++ 03은 부수적 인 것과 마찬가지로 로컬 기능을 정의하는 로터리 방법을 가지고 있습니다. 로컬 계급 기능을 남용해야합니다.

int main()
{
    struct Local
    {
        static string Some()
        {
            return "";
        }
    };
    std::cout << Local::Some() << std::endl;
}

이것은 C ++가 채택한 C와 같은 C의 협약입니다.

C의 다른 함수 내부에서 함수를 선언 할 수있는 능력은 대부분의 프로그래머가 아마도 유감스럽고 불필요하다고 생각하는 결정입니다. 특히 기능 정의가 C보다 비교적 작은 현대 OOP 디자인의 경우

다른 함수의 범위에만 존재하는 함수를 원한다면 두 가지 옵션은 다음과 같습니다. 부스트 :: 람다 그리고 C ++ 1x 람다.

당신의 선언이 왜

void f() {
    void g(); g();
}

이 것보다 낫습니다

void g();
void f() {
    g();
}

가능한 한 로컬로 선언을 유지하면 가능한 한 적은 이름으로 충돌하는 경우 일반적으로 좋습니다. 나는 로컬로 (이 방법) 기능을 선언하는지 여부는 논쟁의 여지가 있다고 말합니다. 진짜 운 좋게도, 나는 여전히 평범한 것이 더 낫다고 생각하기 때문에 헤더를 포함하고 "일반적인"방식으로 가고, 이에 대해 알지 못하는 사람들에게는 덜 혼란 스럽습니다. 때로는 그림자 기능을 중심으로 작업하는 것이 유용합니다.

void f() {
    int g; 
    // oops, ::g is shadowed. But we can work around that
    {
        void g(); g();
    }
}

물론 C ++에서는 기능을 호출 할 수 있습니다. g 사용 its_namespace::g() - 그러나 C의 옛날에는 불가능했을 것이며, 그 일은 프로그래머가 여전히 함수에 액세스 할 수있게 해주었다. 또한 구문 적으로는 동일하지 않지만 의미 적으로 다음은 로컬 범위 내에서 함수를 선언하여 실제로 다른 범위를 목표로합니다.

int main() {
    using std::exit;
    exit();
}

참고로, 선언의 대상 범위가있는 것과 같은 더 많은 상황이 있습니다. ~ 아니다 그 선언이 나타나는 범위. 일반적으로, 당신이 선언하는 엔티티는 선언이 나타나는 범위의 구성원이됩니다. 그러나 그것이 항상 그런 것은 아닙니다. 예를 들어 친구 선언을 고려하십시오.

struct X { friend void f() { std::cout << "WoW"; } };
int main() { void f(); f(); } // works!

기능 선언 (및 정의!) f 의 범위 내에서 일어났다 X, 엔티티 (함수 자체)는 Enclosing 네임 스페이스의 구성원이되었습니다.

기능 프로토 타입입니다 힌트 컴파일러 용. 그들은 기능이 다른 곳에서 구현되었음을 나타냅니다. 발견. 더 이상 아무것도.

당신이 할 때 프로토 타입을 선언 할 때 당신은 기본적으로 컴파일러에게 링커가 해결 될 때까지 기다리라고 말합니다. 프로토 타입을 작성하는 위치에 따라 범위 규칙이 적용됩니다. Main () 함수 내에 프로토 타입을 작성하는 기술적으로 잘못된 것은 없습니다 (IMHO는 약간 지저분하지만) 기능은 Main () 내부에서만 로컬로 알려져 있음을 의미합니다. 소스 파일 상단 (또는 더 일반적으로 헤더 파일)의 프로토 타입을 선언 한 경우 프로토 타입/기능이 전체 소스에서 알려져 있습니다.

string foo()
{
  string ret = someString();  // Error
  return ret; 
}

int main(int argc,char**argv)
{
   string someString();
   string s = somestring(); // OK
   ...
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top