简体   繁体   English

C - 结构内的函数

[英]C - function inside struct

Im trying to assign a function inside a struct , so far I have this code:我试图在struct分配一个函数,到目前为止我有这个代码:

typedef struct client_t client_t, *pno;
struct client_t
{
    pid_t pid;
    char password[TAM_MAX]; // -> 50 chars
    pno next;
    
    pno AddClient() 

    {
        /* code */
    }
};

int main()
{
    client_t client;

    // code ..

    client.AddClient();
}
 **Error**: *client.h:24:2: error: expected ':', ',', ';', '}' or '__attribute__' before '{' token.*

Which is the correct way to do it ?哪个是正确的方法?

It can't be done directly, but you can emulate the same thing using function pointers and explicitly passing the "this" parameter:它不能直接完成,但您可以使用函数指针并显式传递“this”参数来模拟相同的事情:

typedef struct client_t client_t, *pno;
struct client_t
{
    pid_t pid;
    char password[TAM_MAX]; // -> 50 chars
    pno next;

    pno (*AddClient)(client_t *); 
};

pno client_t_AddClient(client_t *self) { /* code */ }

int main()
{

    client_t client;
    client.AddClient = client_t_AddClient; // probably really done in some init fn

    //code ..

    client.AddClient(&client);

}

It turns out that doing this, however, doesn't really buy you an awful lot.然而,事实证明,这样做并没有真正给你带来很多好处。 As such, you won't see many C APIs implemented in this style, since you may as well just call your external function and pass the instance.因此,您不会看到许多以这种方式实现的 C API,因为您也可以只调用外部函数并传递实例。

As others have noted, embedding function pointers directly inside your structure is usually reserved for special purposes, like a callback function.正如其他人所指出的,直接在结构中嵌入函数指针通常保留用于特殊目的,例如回调函数。

What you probably want is something more like a virtual method table.您可能想要的是更像虚拟方法表的东西。

typedef struct client_ops_t client_ops_t;
typedef struct client_t client_t, *pno;

struct client_t {
    /* ... */
    client_ops_t *ops;
};

struct client_ops_t {
    pno (*AddClient)(client_t *);
    pno (*RemoveClient)(client_t *);
};

pno AddClient (client_t *client) { return client->ops->AddClient(client); }
pno RemoveClient (client_t *client) { return client->ops->RemoveClient(client); }

Now, adding more operations does not change the size of the client_t structure.现在,添加更多操作不会改变client_t结构的大小。 Now, this kind of flexibility is only useful if you need to define many kinds of clients, or want to allow users of your client_t interface to be able to augment how the operations behave.现在,这种灵活性仅在您需要定义多种客户端或希望允许client_t接口的用户能够增强操作的行为方式时才有用。

This kind of structure does appear in real code.这种结构确实出现在实际代码中。 The OpenSSL BIO layer looks similar to this, and also UNIX device driver interfaces have a layer like this. OpenSSL BIO 层看起来与此类似,而且 UNIX 设备驱动程序接口也有这样一个层。

How about this?这个怎么样?

#include <stdio.h>

typedef struct hello {
    int (*someFunction)();
} hello;

int foo() {
    return 0;
}

hello Hello() {
    struct hello aHello;
    aHello.someFunction = &foo;
    return aHello;
}

int main()
{
    struct hello aHello = Hello();
    printf("Print hello: %d\n", aHello.someFunction());

    return 0;
} 

This will only work in C++.这仅适用于 C++。 Functions in structs are not a feature of C.结构体中的函数不是 C 的特性。

Same goes for your client.AddClient();同样适用于您的 client.AddClient(); call ... this is a call for a member function, which is object oriented programming, ie C++. call ...这是对成员函数的调用,是面向对象的编程,即C++。

Convert your source to a .cpp file and make sure you are compiling accordingly.将您的源代码转换为 .cpp 文件并确保您进行了相应的编译。

If you need to stick to C, the code below is (sort of) the equivalent:如果你需要坚持使用 C,下面的代码是(有点)等价的:

typedef struct client_t client_t, *pno;
struct client_t
{
        pid_t pid;
        char password[TAM_MAX]; // -> 50 chars
        pno next;

};


pno AddClient(pno *pclient) 
{
    /* code */
}


int main()
{

    client_t client;

    //code ..

    AddClient(client);

}

You are trying to group code according to struct.您正在尝试根据结构对代码进行分组。 C grouping is by file. C 分组是按文件的。 You put all the functions and internal variables in a header or a header and a object ".o" file compiled from ac source file.你把所有的函数和内部变量放在一个头文件或一个头文件和一个从 ac 源文件编译的对象“.o”文件中。

It is not necessary to reinvent object-orientation from scratch for a C program, which is not an object oriented language.没有必要为 C 程序从头开始重新发明面向对象,C 程序不是面向对象的语言。

I have seen this before.我以前见过这个。 It is a strange thing.这是一件奇怪的事情。 Coders, some of them, have an aversion to passing an object they want to change into a function to change it, even though that is the standard way to do so.编码人员,其中一些人,厌恶将他们想要更改的对象传递为一个函数来更改它,即使这是这样做的标准方法。

I blame C++, because it hid the fact that the class object is always the first parameter in a member function, but it is hidden.我责怪 C++,因为它隐藏了类对象始终是成员函数中的第一个参数的事实,但它被隐藏了。 So it looks like it is not passing the object into the function, even though it is.所以看起来它没有将对象传递给函数,即使它是。

Client.addClient(Client& c); // addClient first parameter is actually 
                             // "this", a pointer to the Client object.

C is flexible and can take passing things by reference. C 很灵活,可以通过引用传递事物。

AC function often returns only a status byte or int and that is often ignored. AC 函数通常只返回一个状态字节或 int 并且经常被忽略。 In your case a proper form might be在您的情况下,适当的形式可能是

 /* add client to struct, return 0 on success */
 err = addClient( container_t  cnt, client_t c);
 if ( err != 0 )
   { 
      fprintf(stderr, "could not add client (%d) \n", err ); 
   }

addClient would be in Client.h or Client.c addClient 将在 Client.h 或 Client.c 中

You can pass the struct pointer to function as function argument.您可以将结构指针作为函数参数传递给函数。 It called pass by reference.它称为按引用传递。

If you modify something inside that pointer, the others will be updated to.如果您修改该指针内的某些内容,则其他内容将更新为。 Try like this:像这样尝试:

typedef struct client_t client_t, *pno;
struct client_t
{
        pid_t pid;
        char password[TAM_MAX]; // -> 50 chars
        pno next;
};

pno AddClient(client_t *client)
{
        /* this will change the original client value */
        client.password = "secret";
}

int main()
{
    client_t client;

    //code ..

    AddClient(&client);
}

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

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