結構體中的指針函數以及“結構體”的繼承

轉載自 herowuking
最終編輯 herowuking
結構體中的指針函數以及“結構體”的繼承

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

struct Fruit
{
void (*output)(void);
int i;
};

struct Apple
{
struct Fruit n;
void (*output)(void);
};

void output_base(void);
void output_driven(void);
void output_apple(void);

int main()
{
struct Fruit *p;
struct Apple *q;
struct Fruit base;
struct Apple driven;
base.i = 0;
base.output = output_base;
driven.n.i = 1;
driven.n.output = output_driven;
driven.output = output_apple;
p = &base;
printf("base's i is %d/n",p->i);
p->output();
p = (Fruit *)&driven;
printf("driven's i is %d/n",p->i);
q = &driven;
q->output();
getchar();
return 0;
}

void output_base(void)
{
printf("this is the base/n");
}

void output_driven(void)
{
printf("this is the driven/n");
}

void output_apple()
{
printf("this is apple's output/n");
}

******************************************************************
【相關帖子】結構體中指向函數的指針
結構體中指向函數的指針
C語言中的struct是最接近類的概念,但是在C語言的struct中只有成員,不能有函數,但是可以有指向函數的指針,這也就

方便了我們使用函數了。舉個例子,如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct student
{
int id;
char name[50];
void (*initial)();
void (*process)(int id, char *name);
void (*destroy)();
}stu;
void initial()
{
printf("initialization.../n");
}
void process(int id, char *name)
{
printf("process.../n%d/t%s/n",id, name);
}
void destroy()
{
printf("destroy.../n");
}
int main()
{
stu *stu1;
//在VC和TC下都需要malloc也可以正常運行,但是linux gcc下就會出錯,爲段錯誤,必須malloc
stu1=(stu *)malloc(sizeof(stu));
// 使用的時候必須要先初始化
stu1->id=1000;
strcpy(stu1->name,"xufeng");
stu1->initial=initial;
stu1->process=process;
stu1->destroy=destroy;
printf("%d/t%s/n",stu1->id,stu1->name);
stu1->initial();
stu1->process(stu1->id, stu1->name);
stu1->destroy();
free(stu1);
return 0;
}
------------------------------------
c語言中,如何在結構體中實現函數的功能?把結構體做成和類相似,讓他的內部有屬性,也有方法
這樣的結構體一般稱爲協議類,提供參考:
struct {
int funcid;
char *funcname;
int (*funcint)(); /* 函數指針 int 類型*/
void (*funcvoid)(); /* 函數指針 void類型*/
};
每次都需要初始化,比較麻煩
******************************************************************
【相關帖子】函數中使用結構體指針改變成員變量的值怎麼不能傳遞到主函數中去

程序代碼如下:
#include <stdlib.h>#include <iostream.h>

struct TNode
{
int data ;
TNode *lchild ;
TNode *rchild ;
} ;

void CreateTree(TNode *T , int A[] , int begin , int end)
{
if (begin > end)
{
T = NULL ;
return ;
}

int index = 0.5 * (begin + end) ;

T = (TNode*)malloc(sizeof(TNode)) ;

T->data = A[index] ;

CreateTree(T->lchild , A , begin , index - 1) ;

CreateTree(T->rchild , A , index + 1 , end) ;
}


void main()
{
int A[10] ;

for (int i = 0 ; i < 10 ; i++)
{
A[i] = i ;
}

TNode *T ;

CreateTree(T , A , 0 , 9) ;

cout << T->data << endl ;
}
程序運行不太對,錯誤就出在CreateTree函數中創建的T節點的的成員變量值沒有傳遞出去,但是CreateTree函數的形參是指向結構體的指針啊,爲什麼會出現這種問題呢?
----------------------------------------------------------------------
void CreateTree(TNode* &T , int A[] , int begin , int end)
----------
改成對指針的引用...
--------------------------------------------------------
使用引用
--------------------------------------------------------
爲什麼要加引用呢?T已經是指向結構體的指針了,應該可以將改變後的信息傳遞到主函數中啊
-------------------------------------------------------
儘管加引用後運行結果是正確的

--------------------------------------------------------

因爲需要將指針自身傳出去
如果在函數外面分配空間就不需要引用了
--------------------------------------------------------
如果需要改變變量的值,那麼就應該傳變量的指針(地址),
如果需要改變指針的值,那麼就應該傳指針的指針(地址)。

--------------------------------------------------------
不用引用可以用指針的指針
void CreateTree(TNode **T , int A[] , int begin , int end)
{
TNode* newT;

if (begin > end)
{
T = NULL;
return;
}

int index = 0.5 * (begin + end);

newT = (TNode*)malloc(sizeof(TNode));
*T = newT;

newT->data = A[index] ;

CreateTree(&newT->lchild , A , begin , index - 1) ;

CreateTree(&newT->rchild , A , index + 1 , end) ;
}


void main()
{
int A[10] ;

for (int i = 0 ; i < 10 ; i++)
{
A[i] = i ;
}

TNode *T ;

CreateTree(&T , A , 0 , 9) ;

cout << T->data << endl ;
}

--------------------------------------------------------
哦,我明白了,謝謝各位了,結帖
******************************************************************************
【相關帖子】函數給作爲參數傳遞的結構體指針的結構體成員賦值
char func(struct compABC *ABC)              ////正確
{
ABC->member1 = 12;
ABC->member2 = 34;
}

char func(struct compABC *ABC)    ////錯誤,根據 K&R C 相關章節的說明,-> 運算符也比 * 優先
{
*ABC->member1 = 12;
*ABC->member2 = 34;
}

char func(struct compABC *ABC)         ////錯誤,點號(.)比星號(*)優先
{
*ABC.member1 = 12;
*ABC.member2 = 34;
}

char func(struct compABC *ABC)                ////正確
{
(*ABC).member1 = 12;
(*ABC).member2 = 34;
}

附:什麼是 K&R C

C語言由Dennis M. Ritchie在1973年設計和實現。從那以後使用者逐漸增加。到1978年Ritchie和Bell實驗室的另一位程序專家Kernighan合寫了著名的《The C Programming Language》,將C語言推向全世界,許多國家都出了譯本,國內有一些C語言書就是這本書的翻譯或者編譯。由這本書定義的C語言後來被人們稱作 K&R C。

隨着C語言使用得越來越廣泛,出現了許多新問題,人們日益強烈地要求對C語言進行標準化。這個標準化的工作在美國國家標準局(ANSI)的框架中進行(1983-1988),最終結果是1988年10月頒佈的ANSI標準X3.159-1989,也就是後來人們所說的ANSI C標準。由這個標準定義的C語言被稱作ANSI C。

ANSI C標準很快被採納爲國際標準和各國的標準。國際標準爲ISO/IEC 9899-1990,中國國家標準GB/T 15272-94是國際ISO標準的中文翻譯。

ANSI C標準化工作的一個主要目標是清除原來C語言中的不安全、不合理、不精確、不完善的東西。由此也產生了ANSI C與K&R C之間的差異。從總體上看,這些差異反應的是C語言走向完善、走向成熟。

 



ANSI C 對 K&R C 的修訂

(本段根據《C Programming Language》和C語言標準整理。不求完整,希望列出最常見的差異)

  1. 對於源文件內部的標識符,有效的最小長度擴充到31個字符。文件間連接時,標識符的最小有效長度仍然爲6個字符。(許多實現都支持更大的長度)
  2. 增加了幾個新關鍵字:void,const,volatile,signed,enum。拋棄了老關鍵字entry。
  3. 在換意字符 / 之後寫非規定的序列,其作用確定爲無定義。
  4. 規定8和9都不是八進制數的合法字符。
  5. 引進了數的後綴字符:整數的U和L,浮點數的F和L。
  6. 規定連續出現的字符串常量將被拼接在一起。
  7. 引進了“寬字符”的概念。
  8. 將字符也確定爲帶符號(signed)和不帶符號(unsigned)的。
  9. 丟棄了long float(原來作爲double的同義詞)。
  10. 引入了void類型,用 (void*) 表示通用指針的類型(過去人們通常用 (char*))。
  11. 對算術類型規定了最小表示範圍。要求每個C語言系統用頭文件(<limits.h>和<float.h>)說明實現中的具體規定。
  12. 引進了枚舉定義enum。
  13. 採用了來自C++的類型修飾符,如const。
  14. 規定字符串常量是不可修改的。
  15. 改變了算術類型的隱含轉換規則。
  16. 刪去了一些過時賦值運算符,如 =+。規定賦值運算符都是基本單詞,如 += 之間不能有空格分隔。
  17. 引進了與一元 - 運算符對應的一元 + 運算符。
  18. 指向函數的指針可以直接放在函數調用的位置,不必顯式地寫間接操作。
  19. 允許結構地整體賦值,作爲函數參數和返回值傳遞。
  20. 允許將取地址運算符作用於數組,得到的是指向有關數組的指針。
  21. 標準規定 sizeof 運算符的返回值爲 size_t 類型(某個無符號整型),這一類型在標準頭文件<stddef.h>裏定義。同時在那裏定義的還有 ptrdiff_t 類型,它是指針減運算的結果類型。
  22. 規定取地址運算符不能作用於 register 變量。
  23. 規定移位表達式的類型爲其左運算對象的類型。
  24. 允許建立指向過數組末元素一個位置的指針,以及對它的算術運算和關係運算。
  25. (從C++)引進了包含參數類型的函數原型概念,引進了變長參數表函數的概念。仍允許老的形式,但僅僅是作爲過時形式保留。
  26. 標準規定任何局部聲明的作用域僅僅是當前的塊(複合語句)。
  27. 規定函數參數作爲加入函數體(複合語句)的聲明,因此不能用變量聲明去覆蓋。
  28. 有關名字空間的規定:所有結構、聯合和枚舉標記在一個名字空間裏,標號是另一個名字空間。
  29. 聯合變量在定義時也可以初始化,規定初始化其第一個成分。
  30. 自動結構、聯合和數組也可以初始化,但限制其初始化方式(其中只能包含常量表達式)。
  31. 帶大小描述的字符數組也可以用大小與之相同的字符串常量初始化(結束的 /0 被刪除)。
  32. 開關語句的控制表達式和case標號可以是任何整型的(包括字符類型)。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章