在C语言中实现构造函数的正确方法

问题描述 投票:0回答:1

我想用C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.

我的尝试。

#include <stdio.h>

struct line {
    void (*add_line_ptr)(struct line*, int x, int y);
    int x;
    int y;
};

void add_line(struct line* lptr, int x, int y)
{
    lptr->x = x;
    lptr->y = y;
}


int main()
{
    struct line line1 = {add_line, 0, 0};
    line1.add_line_ptr(&line1, 10, 20);
    printf("%d %d\n", line1.x, line1.y);
}

我认为使用 line1.add_line(&line1, 有什么方法可以在不传递 "object"(struct)指针的情况下实现这个功能吗? 或者其他我没有想到的方法?

c constructor
1个回答
5
投票

仅仅为了模仿类似C++的语法而使用函数指针是很混乱的,没有明显的好处。在C语言中无论做什么都不会有RAII,所以你需要显式地调用构造函数destructors。如果你通过键入 obj.foo()obj = foo() 与OO完全没有关系,这仅仅是编码风格。

但这里的主要问题是,你的代码没有正确的OO设计,因为结构体是完全开放的,没有使用私有封装。出于同样的原因 class line { public: int x; int y; }; 也不是正确的OO--你不会因为把一些相关的变量砸成一个集合类型就得到OO,不管是什么语言。

"最干净""最漂亮 "将意味着完全的私有封装。在C语言中,可以通过不透明类型来实现。我更倾向于在实现它们的时候不把指针隐藏在 typedef 后面,所以。

line.h

#include <stdio.h>
#include <stdlib.h>

typedef struct line line; // forward declaration of incomplete type

line* line_construct (int x, int y);

line.c

#include "line.h"

struct line {    // actual definition of the struct, local to line.c
    int x;       // private variable
    int y;       // private variable
};

line* line_construct (int x, int y)
{
  line* obj = malloc (sizeof *obj); 
  if(obj == NULL) { /* error handling here */ } 

  obj->x = x;
  obj->y = y;

  return obj;
}

行.c

#include "line.h"

int main(void)
{
    line* x = line_construct(10, 20);
}

在这里 line 是100%封装的,调用者无法访问结构的内容。由于我没有在 typedef 后面隐藏指针,所以调用者必须始终使用 line* 指针,永远不能直接声明对象的实例。

如果构造函数只是为了将结构成员归零,那么它不需要得到任何参数的传递,而是可以在内部进行传递。

而很显然,你需要实现一个相应的destructor与 free 以及。line* line_destruct(line* obj) { free(obj); return NULL; } 左右。


2
投票

我不会一开始就把初始化器放到你的结构中。其他函数,当然,但不是第一个。像这样。

#include <stdio.h>

struct line {
    int x;
    int y;
};

void add_line(struct line *lptr, int x, int y)
{
    lptr->x = x;
    lptr->y = y;
}


int main()
{
    struct line line1 = {0, 0};
    add_line(&line1, 10, 20);
    printf("%d %d\n", line1.x, line1.y);
}

原因是你必须在分配结构后分配初始化器 不管是隐式还是显式的. 在OOP语言中,你通常只需命名一次你想要的类,分配器和初始化器都会运行。在C语言中,你必须分别运行它们。无论你是在堆栈上还是在堆上分配一个对象,你都必须至少显式地命名一次你要调用的函数。

热门问题
推荐问题
最新问题