programing

명명되지 않은 구조체의 전달 선언

subpage 2023. 6. 13. 22:19
반응형

명명되지 않은 구조체의 전달 선언

현상금 질문: 자, 이 두 가지는Foos는 같은 것이 아닙니다.좋습니다. 두 번째 양식은 도서관에서 드립니다.변경할 수 없는 상황에서 어떻게 미리 신고해야 합니까?


저는 항상 반복적인 정의가 없다면 C와 C++가 반복적인 선언을 허용한다고 생각했습니다.그러던 중 C 라이브러리를 확장하는 C++ 코드를 작성하려고 할 때 이 문제를 발견했습니다.

struct Foo;
typedef struct {} Foo;

이 경우 다음 오류가 발생합니다.

'struct Foo'에는 'struct Foo'라는 이전 선언이 있습니다.

나는 선언하고 싶어, 젠장!여기 왜 그래요?

typedefef-anonymous struct는 C++03 이전의 작업 방식이며 주로 C99 이전의 컴파일러와의 호환성을 유지하기 위한 것입니다.

지금이 2011년이고, C++과 C가 모두 변경되었다는 것을 고려할 때, 저는 왜 그러한 라이브러리의 최신 버전이 더 이상 없는지 궁금합니다!

더 이상 개발 중이 아니라면 "떠날" 수 없고, 그저 "생존"하고 변화시키는 것이 그 방법입니다.아직 배포 중인 경우, 문제를 개발 팀에 제출합니다.

해결 방법이 필요한 경우 구조가 상속될 수 있음을 고려하십시오.그래서 다음과 같이 선언문을 작성합니다.

struct MyFoo;

다음과 같이 정의합니다.

#include "old_library.h"
struct MyFoo: public Foo {};

그리고 당신의 모든 코드에서, 잊어버려요.Foo그리고 항상 사용합니다.MyFoo.

동일한 이름을 가진 두 개의 서로 다른 엔티티를 선언하는 것입니다. 번째, 첫째번,struct Foo이름이 지정된 구조입니다.Foo두 번째는 익명 구조의 별칭입니다.

대신 수행하는 경우:

struct Foo;
struct Foo {};

효과가 있어요, 왜냐하면 당신은 당신이 다음과 같은 구조를 선언하기 때문입니다.Foo두 가지 상황에서

익명 구조체는 전달할 수 없습니다.전체 정의를 포함하거나 헤더를 변경하고 구조 이름을 지정하는 두 가지 선택사항이 남아 있습니다.

유사한 상황에서, 나는 다음과 같은 것을 가진 레거시 C 헤더는 다음과 같습니다.

== old_library.h ==
typedef struct { int data; } Foo;
== /old_library.h ==

개인 메서드에 대한 매개 변수로 C++ 클래스에서 사용합니다.

class C {
  void run(Foo *ds);
  ...
}

#을(를) 피하려면 "old_library"를 포함합니다.h"는 C.hpp에서 다음과 같은 포워드 선언을 사용합니다.

class C {
  struct Foo;
  void run(Foo *ds);
  ...
}

그리고 C.cpp에서 저는 다음과 같은 진술을 합니다.

extern "C" {
#include "old_library.h"
}
struct C::Foo : public ::Foo {};

이런 식으로 C::를 사용합니다.투명하게 Foo 대신 Foo, 그리고 My Foo는 필요하지 않습니다!

C++로 defect를 입력할 필요가 없습니다.

struct Foo;     // Forward declaration

struct Foo 
{

}; // Definition

만당이그그냥을것신약▁it그냥▁if▁you▁just▁to.Foostruct FooC에서 typeef가 필요합니다. typeef는 다양한 방법으로 수행할 수 있습니다.

struct Foo;     /* Forward declaration */

struct Foo /* The name is needed here */
{

}; /* Definition */
typedef struct Foo Foo;  /* typedef */

또는

struct Foo;     /* Forward declaration */

typedef struct Foo /* The name is needed here */
{

} Foo; /* Definition and typedef combined */

물론 양식을 사용할 수 있습니다.struct FooC와 C++ 모두에서.

당신의 전진 선언은 다음이 있을 것이라고 선언합니다.struct라고 하는Foo.

의 두 입니다.typedef라고 하는Foo이것들은 같은 것이 아닙니다.

typedef의 정방향 선언을 위해서는 다음과 같이 typedef로 입력되는 것을 참조해야 합니다.

struct foo;
typedef foo bar;
class foo{};

익명 구조체를 정방향으로 선언하려고 하므로 원래 도면요소의 정방향 선언에서 이름을 지정할 수 없으며, 이를 정의할 때 참조할 수도 없습니다.논리적 구문은 다음과 같습니다.

struct ;
typedef bar;
class {};

그러나 이것은 분명히 불가능하기 때문에 익명 구조를 전달할 수 없습니다.

표준화하려면 9.1-2를 살펴보겠습니다.

클래스 키 식별자로만 구성된 선언. 현재 범위의 이름을 다시 선언하거나 식별자를 클래스 이름으로 전달하는 선언입니다.클래스 이름이 현재 범위에 추가됩니다.

식별자도, 전달 선언도 없습니다.

이것의 핵심: 익명 구조물이 당신에게 정말 필요한 이점을 제공하지 않는 한 그것들을 피하세요.

여기서 특정 컴파일러에 따라 달라질 수 있습니다.

MinGW 두 선언 모두 GCC 3.4.5 사용).-Wall)

struct Foo;
typedef struct {} Foo;

그리고.

struct Foo;
typedef struct Foo {} Foo;

도서관 내에 사전 신고가 이미 존재할 가능성이 있습니까?예를 들어 원형 포인터를 허용하려면:

struct Foo;
typedef struct Foo {
    struct Foo *fooPtr;
} Foo;

라이브러리 헤더 내에 이미 존재하는 경우 설명하는 오류가 발생합니다.

IMHO를 , 간히변수있다니습.typedef

typedef struct Foo {} Foo;
              ^^^^^

손상은 없으며 C와 C++ 모두에서 여전히 호환됩니다.이제 이를 포워드 선언할 수 있습니다.

[참고: 만약 당신이 여전히 만지지 않겠다고 고집한다면,typedef그렇다면 여기 더러운 속임수가 있습니다.

struct Foo;
#define struct struct Foo
#include"Foo.h"  // contains typedef struct {} Foo;
#undef struct

이것은 효과가 있을 것입니다, 오직.Foo.h의 만합니다만.struct선언.추천하지 않습니다.]

최근에 원래 포스터와 동일한 문제가 발생하여 아래와 같이 해결한 것 같습니다.

저는 다음과 같이 정의된 타사 제공 API에 대한 래퍼를 작성하고 있습니다.

Foo.h:

typedef struct _foo 
{
    int i;
} Foo;

Foo* MakeFoo();
int UseFoo(Foo* foo);

제 포장지에는 Foo가 회원으로 있어야 하는데, 저는 Foo를 제 포장지의 모든 소비자들에게 노출시키고 싶지 않습니다.

Uber Foo.h:

#pragma once

struct _foo;  // forward declare the actual type _foo, not the typedef Foo

class UberFoo
{
public:
    UberFoo();
    int GetAnswer();
private:
    _foo* f;
};

UberFoo.cpp:

#include "UberFoo.h"
#include "Foo.h"

UberFoo::UberFoo()
{
    this->f = MakeFoo();
}

int UberFoo::GetAnswer()
{
    return UseFoo(f);
}

이제 우리 클래스의 소비자들은 _foo/Foo의 실제 정의에 액세스하지 않고도 인스턴스화할 수 있습니다.이것은 _foo에 대한 포인터를 매개 변수로 전달하거나 _foo 멤버가 있을 뿐만 아니라 함수에서 반환해야 할 경우에도 작동합니다.

main.cpp:

#include <cstdio>
#include "UberFoo.h"

int main(int argc, char* argv[])
{
    UberFoo u;
    printf( "The Answer = %d\n", u.GetAnswer());
    return 0;
}

여기서 요령은 형식 정의 이름이 아니라 실제 구조 유형을 포워드 선언하는 것이었습니다.오래된 C 코드에서 흔히 볼 수 있는 것처럼 구조가 익명이 아닌 것이 중요합니다.

typedef struct // the actual struct type underlying the typedef is anonymous here
{
    int i;
} ThisWontWork;

이것이 도움이 되길 바랍니다!

이름이 없기 때문에 전달할 수 없습니다.Foo가 typedef인 이름 없는 구조입니다.

그냥 전진 선언을 피하는 게 어때요?

두 번째 정의가 헤더 파일에 있는 경우 먼저 C++ 헤더 파일에 헤더 파일을 포함할 수 있습니다.C++를 C 헤더로 생각하게 하려면 #include with를 포함합니다.extern "C" {그리고.}대부분의 경우 충분해야 합니다.

이전에 사용한 이름을 입력하려고 합니다.성명서는 완전히 유효하며 다른 이름만 사용하면 됩니다.

struct Foo; // Forward declaration of struct Foo
typedef struct {} anotherFoo; // Another structure typedefed
struct Foo {
 // Variables
}; // Definition of the forward declared Foo.

typeef는 동일한 이름으로 사용할 수 없습니다.

언급URL : https://stackoverflow.com/questions/7256436/forward-declarations-of-unnamed-struct

반응형