2015-09-28 47 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文件中就可以了。