我已经构建了一个通用的二进制搜索树。
typedef struct Tree {
void* data;
struct Tree *left;
struct Tree *right;
}Tree;
使用不同数据类型变量创建树的两个函数。
Tree* GetNewTreeInt(){
Tree* newTree = (Tree*)malloc(sizeof(Tree));
*((int*)newTree->data);
newTree->left = newTree->right = NULL;
return newTree;
}
Tree* GetNewTreeChar(){
Tree* newTree = (Tree*)malloc(sizeof(Tree));
*((char*)newTree->data);
newTree->left = newTree->right = NULL;
return newTree;
}
我试图创建一个通过地址存储函数的通用函数
Tree* CreateTree();
int main() {
void* root;
scanf("%d", &choose);
if(choose==0){
Tree* CreateTree=GetNewTreeInt();
(Tree*)root=CreateTree();
}
但是我一直收到以下错误:调用对象类型“Tree *”(又名'struct Tree *')不是函数或函数指针
答案 0 :(得分:2)
此:
Tree* CreateTree();
..声明一个函数CreateTree
,它返回一个Tree*
,没有完全定义函数(没有函数体,只是一个原型)。鉴于此:
Tree* CreateTree=GetNewTreeInt();
声明名为Tree*
的{{1}}类型的变量,并调用CreateTree
函数将其返回值赋给GetNewTreeInt()
。由于您已经声明了具有相同名称的函数,因此这会给您带来错误。
如果您希望CreateTree
成为函数指针,并将其指向CreateTree
函数,则需要将其声明为(全局或GetNewTreeInt
内,而不是两者) :
main
..然后将其指向Tree *(*CreateTree)();
,如下所示:
GetNewTreeInt
..然后您可以通过指针调用函数,只需CreateTree = GetNewTreeInt;
和普通函数一样,例如:
CreateTree()
如果需要函数指针类型的typedef,可以按如下方式执行:
root = CreateTree();
...并将typedef Tree *(*CreateTreeFuncType)();
声明为:
CreateTree
而不是使用前面提到的函数指针语法。
答案 1 :(得分:1)
看起来你正在尝试使用函数指针。要做到这一点,你需要声明一个函数指针,该函数指向一个函数,该函数直接返回Tree*
而不是Tree*
:
if(choose==0) {
Tree* (*CreateTree)(void);
CreateTree = &GetNewTreeInt;
}
但是,您的两个函数是相同的,因为行*((int*)newTree->data);
没有副作用。您可以创建一个这样的函数:
Tree* GetNewTreeInt(void){
Tree* newTree = (Tree*)malloc(sizeof(Tree));
newTree->left = newTree->right = NULL;
return newTree;
}
当您访问tree->data
时需要将void *
强制转换为您知道其包含的类型的指针。如果您不知道外部具有哪种类型的树,则应该在结构中添加另一个字段,表示存储的数据类型。如果您只存储int
和char
等小数据类型,我建议使用union而不是void指针,因为union会将数据存储在内存中。无论哪种方式,您仍然需要树中的某些内容来指示其存储的数据类型。
typedef struct Tree {
// 0 means there is an int in tree->data.i,
// 1 means there is a char in tree->data.c
int type;
union {
int i;
char c;
} data;
struct Tree *left;
struct Tree *right;
} Tree;
然后你的两个功能变为:
Tree* GetNewTreeInt(void){
Tree* newTree = (Tree*)malloc(sizeof(Tree));
newTree->type = 0;
newTree->data.i = 0; // Set an initial value
newTree->left = newTree->right = NULL;
return newTree;
}
Tree* GetNewTreeChar(void){
Tree* newTree = (Tree*)malloc(sizeof(Tree));
newTree->type = 1;
newTree->data.c = '\0'; // Set an initial value
newTree->left = newTree->right = NULL;
return newTree;
}
你可以像这样使用函数指针:
if(choose==0) {
Tree* (*CreateTree)(void);
CreateTree = &GetNewTreeInt;
Tree* tree = CreateTree();
tree->data.i = 7;
}
每棵树都有一个data.i
或data.c
,但不是两者都有,稍后当您浏览树木时,您可以检查其类型以找出哪个:
if ( tree->type == 0 ) {
int data = tree->data.i;
} else if ( tree->type == 1 ) {
char data = tree->data.c;
}
修改强>
如果您真的想使用void *
,您仍然可以将int type
添加到您的结构中,并且在遍历时您可以执行以下操作:
if ( tree->type == 0 ) {
int data = *(int *)tree->data;
} else if ( tree->type == 1 ) {
char data = *(char *)tree->data;
}