简体   繁体   English

OOP 和 C 中结构的前向声明

[英]OOP and forward declaration of structure in C

I am studying C language and have recently learned how to write the OOP using C.我正在学习 C 语言,最近学习了如何使用 C 编写 OOP。 Most part of it was not hard that much to understand for me except the name of structures type used to create new class.除了用于创建新 class 的结构类型的名称外,对我来说大部分内容并不难理解。

My textbook used struct dummy_t for forward declaration and typedef struct {...} dummy_t for its definition.我的教科书使用struct dummy_t进行前向声明,使用typedef struct {...} dummy_t进行定义。 In my understanding, these are two different type because the former is struct dummy type and the later is struct type without a name tag but the sample code from the textbook worked well.在我的理解中,这是两种不同的类型,因为前者是struct dummy类型,而后者是没有名称标签的struct类型,但教科书中的示例代码运行良好。

So I deliberately modified the sample code so that the difference in the names of structures will be much clearer.所以我特意修改了示例代码,以便结构名称的区别更加清晰。 Below are the lines of code I tried.以下是我尝试过的代码行。

//class.h

struct test_a;
struct test_a * test_init(void);
void test_print(struct test_a*);
//class.c
#include <stdio.h>
#include <stdlib.h>

typedef struct dummy{
    int x;
    int y;
} test_b;

test_b * test_init(void){
    test_b * temp = (test_b *) malloc(sizeof(test_b));
    temp->x = 10;
    temp->y = 11;
    return temp;
}

void test_print(test_b* obj){
    printf("x: %d, y: %d\n", obj->x, obj->y);
}
//main.c
#include "class.h"

int main(void){
    struct test_a * obj;
    obj = test_init();
    test_print(obj);

    return 0;
}
// It printed "x: 10, y: 10"

As you can see, I used struct test_a for forward declaration and typedef struct dummy {...} test_b for definition.如您所见,我使用struct test_a进行前向声明,使用typedef struct dummy {...} test_b进行定义。 I am wondering why I did not get the compile error and it worked.我想知道为什么我没有得到编译错误并且它起作用了。

It 'worked' because you did not include class.h in class.c .它“有效”是因为您没有在class.c class.h So the compiler can't see the implementation does not match the declaration.所以编译器看不到实现与声明不匹配。

The proper way is (but without the typedef for clarity):正确的方法是(但为了清楚起见没有 typedef):

// class.h
struct test_a;
struct test_a* test_init(void);

//class.c
#include "class.h"
struct test_a {
    int x;
    int y;
};

struct test_a* test_init(void)
{
   ...
}

The struct test_a in the header file makes the name test_a known to the compiler as being a struct. header 文件中的struct test_a使编译器知道名称test_a是一个结构。 But as it does not now what is in the struct you can only use pointers to such a struct.但是由于它现在没有结构中的内容,因此您只能使用指向此类结构的指针。

The members are defined in the implementation file and can only be used there.成员在实现文件中定义,只能在那里使用。

If you want to use a typedef:如果你想使用 typedef:

// header
typedef struct test_a_struct test_a;
test_a* test_init(void);

//implementation
struct test_a_struct {
    int x;
    int y;
};
test_a* test_init(void)
{
    ...
}

I am wondering why I did not get the compile error我想知道为什么我没有收到编译错误

When you compile main.c the compiler is told via a forward declaration from class.h that there is a function with the signature struct test_a * test_init(void);当您编译 main.c 时,编译器通过来自 class.h 的前向声明被告知有一个 function 带有签名struct test_a * test_init(void);

The compiler can't do anything other than just trusting that, ie no errors, no warnings can be issued.编译器只能相信它,即不会发出任何错误,也不会发出任何警告。

When you compile class.c there is no forward declaration but only the function definition, ie no errors, no warnings.当您编译class.c时,没有前向声明,只有 function 定义,即没有错误,没有警告。

It's always a good idea to include the.h file into the corresponding.c file.将.h 文件包含到相应的.c 文件中总是一个好主意。 Had you had a #include "class.h" in class.c the compiler would have been able to detect the mismatch.如果您在 class.c 中有一个#include "class.h" ,编译器将能够检测到不匹配。

..and it worked ..它奏效了

What happens is:会发生什么:

  1. A pointer to test_b is assigned to a pointer to test_a variable指向 test_b 的指针被分配给指向 test_a 变量的指针

  2. The variable is then passed as argument to a function expecting a pointer to test_b然后将该变量作为参数传递给 function 期望指向 test_b 的指针

So once you use the pointer it is used as it was created (ie as pointer to test_b).因此,一旦您使用了指针,它就按照创建时的方式使用(即作为指向 test_b 的指针)。 In between you just stored in a variable of another pointer type.在两者之间,您只是存储在另一种指针类型的变量中。

Is that ok?那样行吗? No

Storing a pointer to one type in a object defined for another pointer type is not ok.在为另一种指针类型定义的 object 中存储指向一种类型的指针是不行的。 It's undefined behavior.这是未定义的行为。 In this case it "just happened to work".在这种情况下,它“恰好起作用”。 In real life it will "just happen to work" on most systems because most systems use the same pointer layout for all types.在现实生活中,它会在大多数系统上“碰巧工作”,因为大多数系统对所有类型都使用相同的指针布局。 But according to the C standard it's undefined behavior.但根据 C 标准,这是未定义的行为。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM