Crest簡(jiǎn)單對(duì)象的設(shè)計(jì)
在我們開(kāi)始Crest的設(shè)計(jì)之前,我們先看一段參考代碼
using System;
using System.Collections.Generic;
public abstract class Bird{
protected String name;
public abstract String tweet();
public String getName(){return name;}
}
public class Cock : Bird{
public override String tweet(){return "woooooo";}
public virtual String walk(){return "cock walk";}
public void setName(String newName){ name = newName;}
}
public class MainClass
{
public static void Main()
{
Bird bird = new Cock();
Cock cock = new Cock();
System.Console.WriteLine(bird.tweet());
}
}
這是一段純正的面向?qū)ο蟮拇a,我們的話題就會(huì)沿著這一段代碼展開(kāi)。首先我們從設(shè)計(jì)Crest以支持最簡(jiǎn)單的對(duì)象。
簡(jiǎn)單對(duì)象
因?yàn)镃語(yǔ)言的本身限制,所以我們要模擬一個(gè)類的定義只能使用struct。最簡(jiǎn)單的類當(dāng)然就是空類了。我們的C代碼如下:
struct CEmptyObject
{
}
然后我們要讓我們的CEmptyObject類加入成員變量,也很簡(jiǎn)單:
struct CEmptyObject
{
int salary;
};
再加入一個(gè)成員函數(shù)吧。我想加入一個(gè)getSalary,但是問(wèn)題來(lái)了,怎么加呢?如果這樣寫(xiě):
int getSalary(){return salary;}
似乎是對(duì)的,但是C編譯器報(bào)告salary找不到,如果把這行代碼放到struct CEmptyObject中,同樣也是編譯錯(cuò)誤[BCC32 Error] raw.c(143): E2200 Functions may not be part of a struct or union。實(shí)際上,大部分OO語(yǔ)言的實(shí)現(xiàn)都是類似的,我們也就不賣關(guān)子了,照搬如下:
int getSalary(struct CEmptyObject * _this)
{
return _this->salary;
}
所有我們代碼中寫(xiě)的 xxx.getSalary() 類似的代碼,都實(shí)際轉(zhuǎn)化為getSalary(xxx)形式,如果大家熟悉C#的擴(kuò)展函數(shù),就更明白這一點(diǎn)。
簡(jiǎn)單對(duì)象的使用
設(shè)計(jì)好了簡(jiǎn)單對(duì)象,我們當(dāng)然要用一下了,先看代碼:
int simpleMain()
{
struct CEmptyObject obj;
printf("%d", getSalary(&obj));
}
問(wèn)題來(lái)了,構(gòu)造函數(shù)呢?沒(méi)關(guān)系,先湊合用一下吧,我們用C風(fēng)格的初始化方法,代碼如下:
int simpleMain()
{
struct CEmptyObject obj = {3000};
printf("%d", getSalary(&obj));
}
運(yùn)行正常!但是萬(wàn)一我們要用構(gòu)造函數(shù)怎么辦?沒(méi)關(guān)系,構(gòu)造函數(shù)其實(shí)就是一種特殊的成員函數(shù)而已,那就加上吧:
void CEmptyObject(struct CEmptyObject * _this, int salary)
{
_this->salary = salary;
}
int simpleMain()
{
struct CEmptyObject obj;
CEmptyObject(&obj, 3000);
printf("%d", getSalary(&obj));
}
運(yùn)行還是正常!不過(guò),OO語(yǔ)言里不是經(jīng)常有new動(dòng)作嗎?我們現(xiàn)在模擬的對(duì)象,都實(shí)際創(chuàng)建在stack中,如果我們要用new創(chuàng)建到heap中呢?那就來(lái)模擬new吧!
struct CEmptyObject * new(size_t size)
{
return (struct CEmptyObject *)malloc(size);
};
int simpleMain()
{
struct CEmptyObject obj, *obj2;
CEmptyObject(&obj, 3000);
obj2 = new(sizeof(struct CEmptyObject));
CEmptyObject(obj2, 4000);
printf("%d", getSalary(&obj));
printf("%d", getSalary(obj2));
}
運(yùn)行,看起來(lái)正常!如果你打開(kāi)監(jiān)控,會(huì)有報(bào)告內(nèi)存泄露,因?yàn)槲覀兊膎ew函數(shù)用malloc來(lái)分配了內(nèi)存,而退出的時(shí)候我們沒(méi)有釋放它。所以我們需要同時(shí)實(shí)現(xiàn)一個(gè)delete函數(shù),但是先別動(dòng)手,我們要繼續(xù)談一下析構(gòu)函數(shù)的問(wèn)題。從本質(zhì)上,析構(gòu)函數(shù)也是一個(gè)特殊的成員函數(shù),但是帶來(lái)的問(wèn)題是這個(gè)析構(gòu)函數(shù)何時(shí)調(diào)用。對(duì)于C#、java等有垃圾收集功能的語(yǔ)言來(lái)說(shuō),析構(gòu)函數(shù)會(huì)在銷毀之前調(diào)用(深究則不然,后文會(huì)談),C++則會(huì)在對(duì)象退出作用域之前自動(dòng)調(diào)用,但是這里則要小心了,因?yàn)槲覀冇檬止ふ{(diào)用。
void CEmptyObject(struct CEmptyObject * _this, int salary)
{
_this->salary = salary;
}
void _CEmptyObject(struct CEmptyObject * _this)
{
_this->salary = 0;
}
struct CEmptyObject * new(size_t size)
{
return (struct CEmptyObject *)malloc(size);
};
void delete(struct CEmptyObject *_this)
{
_CEmptyObject(_this);
free(_this);
}
int simpleMain()
{
struct CEmptyObject obj, *obj2;
CEmptyObject(&obj, 3000);
obj2 = new(sizeof(struct CEmptyObject));
CEmptyObject(obj2, 4000);
printf("%d", getSalary(&obj));
printf("%d", getSalary(obj2));
delete(obj2);
_CEmptyObject(&obj);
}
代碼運(yùn)行正常??墒谴蠹沂遣皇怯X(jué)得這樣太繁瑣了阿?寫(xiě)這么多雜七雜八的東西,看起來(lái)一點(diǎn)都不簡(jiǎn)潔。而且bigtall一向認(rèn)為一個(gè)優(yōu)秀的程序員必定是"懶惰"的,他應(yīng)該對(duì)任何形式的"重復(fù)工作"都無(wú)法容忍。所以我們需要用C語(yǔ)言的"宏定義"大法來(lái)改善代碼的可讀性。
上一篇: Crest-大家都來(lái)山寨一個(gè)GObject吧 下一篇: Crest的語(yǔ)法---宏的魔術(shù)匯演

公眾號(hào):老翅寒暑
posted on 2009-11-26 11:45 老翅寒暑 閱讀(1802) 評(píng)論(4) 收藏 舉報(bào)
浙公網(wǎng)安備 33010602011771號(hào)