2017-11-30 18 views
-2

私のCソースファイルにprivate型の構造体をタグとして定義し、構造体型を型に宣言すると、コンテンツがユーザーに表示されず、名前空間はきれいに保たれ、ユーザーは必要ではないファイルを自動的には含めません。C/C++ - 構造体タグ - 不完全型

私はC++で同じことをしようとはしていませんが、許可していないと言っています:不完全な型は定義できません。

// test.cpp --------------------------------- 
#include "test.hpp" 

struct myStructTag_s 
{ 
    int A; 
    int B; 
}; 

// test.hpp --------------------------------- 
#ifndef TEST_HPP_ 
#define TEST_HPP_ 

typedef struct myStructTag_s myStructTag_t; 

#endif /* TEST_HPP_ */ 

// main.cpp --------------------------------- 
#include "test.hpp" 

myStructTag_t A; 

int main() 
{ 
    A.A = 5; 
    return 0; 
} 
+3

をあなたの ' typedef struct myStructTag_s'は不正な構文を使用します - '}'の後に型名があります。 – Ivan

+1

C++では、 'struct'を' typedef'する必要はありません。 'struct'sは暗黙的に型名です。 –

+0

@Ivanこれは私のコードの例でそこにあるとは言えませんでした。私はそれが書かれているように今正しく、しかし動作しません。 –

答えて

1

理由:それはstruct myStructTag_sの宣言はなく、定義を持っているので、

myStructTag_t A; 

です。このタイプは定義が欠落しているため不完全なタイプとみなされます。定義なしで構造体のインスタンスを作成することはできません。

myStructTag_t *A; 

これはあなたがすることができ、このタイプへのポインタを受け入れます。test.cppにおける一連の機能を作成することができます:あなたはしかし、不完全な型へのポインタを作成されて何ができるか

定義がtest.cppに存在するので、これを操作するために使用されます。

のでTEST.CPPはこのような何か含めることができます。test.hppで

myStructTag_t *create(int a, int b) 
{ 
    myStructTag_t *inst = malloc(sizeof(*inst)); 
    inst->A = a; 
    inst->B = b; 
    return inst; 
} 

int getA(myStructTag_t *inst) 
{ 
    return inst->A; 
} 

myStructTag_t *create(int a, int b); 
int getA(myStructTag_t *inst); 

次にあなたがメインで、次の操作を行うことができます。

myStructTag_t *A; 

int main() 
{ 
    A = create(5,0); 
    printf("a=%d\n", getA(A); 
    return 0; 
} 
0

モジュールmain.cppには

// main.cpp --------------------------------- 
#include "test.hpp" 

myStructTag_t A; 

int main() 
{ 
    A.A = 5; 
    return 0; 
} 

をコンパイルした場合、それはその定義を持っていないため、コンパイラはオブジェクトAをインスタンス化することはできません。それは構造がデータメンバAを有し、その種類は何であるかどうかわからないので、だから、それはまた、この文を

A.A = 5; 

を受け入れることはできません。

+0

@wellはtest.hppにありますか? –

+0

そして、もし私が上記のコードがCならmain.c(.cppの代わりに)は型の定義についてまだ分からないでしょう。 – SoronelHaetir

+0

その型定義はありませんが、むしろ次のようなタグがあります。 構造体THIS_IS_THE_TAG_NAME {int a; } THIS_IS_THE_TYPE_NAME。 –

2

このような型へのポインタ以外の不完全な型の使用は、CでもC++でもコンパイルされないことは間違いありません。

理由は、オブジェクトをインスタンス化するために、コンパイラが変換単位を変換するときに、オブジェクトの必要なメモリレイアウトを定義するための完全な構造情報が必要なためです。 main.cppのような翻訳単位では、コンパイラに直接表示されるものだけがmain.cppに直接または間接的に含まれます。

main.cppにはtest.hppしか含まれていません。myStructTag_sという定義はありません。

structを「前方宣言」することはできますが、完全なタイプである限り、つまりstructのメンバーを定義していない限り、そのタイプのオブジェクトを作成することはできません。

プログラムの構築は、基本的に(1)互いに独立して翻訳単位をオブジェクトファイルにコンパイルすること、および(2)生成されたオブジェクトファイルを一緒にリンクするという2段階プロセスであることに注意してください。何らかの型のオブジェクトを定義するだけではなく、型の定義タイプ定義は、リンクフェーズでなく、翻訳単位のコンパイルフェーズのコンパイラに表示する必要があります。あなたがメインで、このような変数を作成することはできません

+0

これはソースファイル(構造体定義)で行われます。構造体にはタグ(名前)があり、型ではないためです。 Cのタグは、コンパイラがインクルード階層から独立したタグのリストを持つ構造体と列挙体で使用できます。 http://ee.hawaii.edu/~tep/EE160/Book/chap12/subsection2.1.1.2.html –

+0

@lunonameあなたのリンクでは、人々が使用するものと矛盾する奇妙な名詞が使用されるため、深刻な誤ったコミュニケーションが使用されます。 [良いC本](https://stackoverflow.com/questions/562303/the-definitive-c-book-guide-and-list)を手に入れることを検討してください。 –

+0

@lu noname:これはタグの問題ではありません。編集された回答を参照してください。 –

関連する問題