2015-09-28 36 views
0

在C.与原始OOP想法进行实验初步OOP用C

main.c中:

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

int main() 
{ 
    const char *name = "Spot"; 
    turtle_t *t = maketurtle(name); 
    t->hide(t); // <---- "Error: dereferencing pointer to incomplete type" 

    return 0; 
} 

reptile.h:

#ifndef REPTILE_H 
#define REPTILE_H 

typedef struct turtle_t turtle_t; 
turtle_t* maketurtle(const char *name); 
void hide(turtle_t *self); 

#endif // REPTILE_H 

reptile.c:

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

typedef struct turtle_t 
{ 
    int numoflegs; 
    const char name[25]; 
    void (*hide)(turtle_t *self); 

} turtle_t; 

turtle_t* maketurtle(const char *name) 
{ 
    turtle_t *t = (turtle_t*)malloc(sizeof(turtle_t)); 
    t->name = name; 
    return t; 
} 

void hide(turtle_t *self) 
{ 
    printf("The turtle %s has withdrawn into his shell!", self->name); 
} 

有什么我失踪?我在堆栈溢出中看过类似的情况,我的代码至少在结构上看起来相同,所以我有点困惑。提前致谢!

p.s.如果这是一个链接器错误,我该如何让它在IDE中编译而不会引发错误?

+1

注意,请考虑在您的方法名称前加上它们所属的类型以避免潜在的命名冲突。 –

+0

另一方面说明:你应该写一个'name'变量的硬拷贝,不要让指针指向字符串。也就是说,用strcpy替换't-> name = name;'。 – Lundin

+0

第三方说明:考虑让你的函数成为'static'。即使你使用你的结构和指向函数的指针,实际的函数本身仍然可以是“静态”的。这可避免在与可能包含具有相同名称的导出函数的其他文件链接时发生名称冲突。 –

回答

4

当编译器在main.c文件上工作时,它知道有一个名为turtle_t的结构,但它对此一无所知,它没有完全定义。

您需要使结构“公开”,或至少应该是公开的部分。这可以通过使用两个结构轻松完成,一个用于公共“方法”和成员变量,另一个用于包含私有数据的嵌套。喜欢的东西

typedef struct turtle_private_t turtle_private_t; 
typedef struct turtle_t turtle_t; 

struct turtle_t 
{ 
    turtle_private_t *private; // For private data 
    void (*hide)(turtle_t *self); 
}; 

作为替代,另外一个是共同的,就是你不要将公共职能的结构,而是使用正常功能,具有特殊的前缀以他们的名字,表示类。类似于

turtle_t *turtle_create(void); // Creates the turtle 
void turtle_hide(turtle_t *); // Hides the turtle 
+0

非常感谢。哪种方法更广泛使用? – Rhurac

+1

这通常是一个更好的主意,不要使结构公开,而是使用不完整的类型将隐藏结构声明给调用者。 – Lundin

+0

@Rhurac后者可能更常见,但是这取决于个人偏好,公司规则或要求以及环境。后一种方式的一个常见示例是,带有前缀的独立公共函数是使用不透明FILE结构的标准I/O函数。 –

4

您需要从.c文件移到您的

typedef struct turtle_t 
{ 
    int numoflegs; 
    const char name[25]; 
    void (*hide)(turtle_t *self); 

} turtle_t; 

到.h文件。不完全类型表示该类型在编译类型中是未知的(只有在链接时才知道,如果它包含在不同的翻译单元中)。这意味着在你的main.c中turtle_t只是前向声明的,而结构本身是未知的 - 将它移动到你的.h文件中就可以了。