2009年10月22日 星期四

物件導向:封裝、繼承、多型

最近身邊很多人在找工作,漫多公司會有考試以及口試中會有技術問答的部分。
以不碰硬體的軟體工程師來說,技術問題我簡略的分成兩類:

偏硬的公司,比較會問記憶體位址相關的問題,如指標、參考等這些一般人比較容易搞不清楚的觀念。
偏軟的公司,比較會問物件導向相關的問題,如物件導向的優點、特性、以及實務上的一些問題。
當然除此之外一些共通的部分像是作業系統或計算機架構,這就看平常在學校有沒有好好學。

我為什麼把問題分成漲兩類呢?因為我發現身旁漫多人可能因為本身習慣的關係,兩種觀念比較無法同時記住。
通常平常很會用指標、參考的人,很可能會對物件導向比較不熟,例如c習慣使用者。
而平常慣用 oop language 的朋友,如 java、c#,則對指標參考等的觀念記憶稍微薄弱一些。

之前有寫過指標類的介紹了,不過似乎有點簡略,之後有空再補完。

今天介紹一下物件導向一些基本概念,這些同時也是找工作筆試面試常會遇到的一些問題。


封裝
我之前都是寫 c# 居多,即使如此,當面試時公司主管問我:物件導向為什麼要封裝?我卻回答的零零落落。
因為平常用的太習慣了,覺得封裝已經是在自然不過的事情,哪需要理由?
基本上這種問題你只要提到 keyword 就好了:
Information hiding, 避免程式各個物件互相干擾,降低程式的複雜度及維護上的困難度。

繼承
繼承的目的:一語概之就是為了 reuse。

多型
多型與超載 (Overloading)與重寫 (Overriding)相關,和上面的繼承更是息息相關。
一個物件如果你看待的方式不同,就可以發揮不同的功用。
這在現實生活中很合理,一個碗可以拿來當容器,也可以拿來盛土種花,當然要倒過來當蓋子也行,甚至,你要拿來砸碎當發聲的樂器也不犯法。
因此同一個物件,在不同的場合,不同的使用情境,就應該合理運作展現應有的效果,這也就是多型的精神。

參考資料:
http://www.ithome.com.tw/itadm/article.php?c=45903
http://140.134.26.7/wbemwiki/index.php/%E7%AC%AC%E4%B8%89%E7%AB%A0_%E7%89%A9%E4%BB%B6%E5%B0%8E%E5%90%91%E8%A8%AD%E8%A8%88

音樂術語

常見的速度術語:
Largo 最緩板 速度♩= 40~60
Larghetto 甚緩板 速度♩= 60~66
Adagio 慢板 速度♩= 66~76
Andante 行板 速度♩= 76~108
Moderato 中板 速度♩=108~120
Allegro 快板 速度♩= 120~168
Presto 急板 速度♩= 168~200
Prestissimo 最急板 速度♩= 200~208

速度漸慢 :
Allargando (allarg.)
Rallentando (rall.)
Ritardando (rit.)

速度漸快:
Accelerando (accel.)

速度還原:(回到正常的速度)
A tempo
Tempo primo

速度任意:(隨意,由演奏者或指揮者自定)
Ad libitum (ad lib.)
Tempo rubato

常見的力度術語:
Pianisissimo (ppp) 最弱
Pianissimo (pp) 甚弱
Piano (p) 弱
Mezzo piano (mp) 中弱
Mezzo forte (mf) 中強
Forte (f) 強
Fortissimo (ff) 甚強
Fortisissimo (fff) 最強

補充:fp 強後立即轉弱 sf.、sfz.、rf.、rfz.、rinf.皆為突強

漸強:
Crescendo (cresc.)

漸弱:
Decrescendo (decresc.)
Diminuendo (dim.)

拿Google Reader看PTT

1.
到 http://www.google.com/reader 登入


2.
左上角有個新增訂閱 按下去
填入你要看的看板
格式是 rss.ptt.cc/看板名稱.xml
例如笨版 就打 rss.ptt.cc/StupidClown.xml
注意大小寫要完全一樣


3.
完成 上班可以逛PTT了= =+



參考資料:http://ipluto.wordpress.com/2009/07/31/%E6%8B%BFgoogle-reader%E7%9C%8Bptt/

2009年10月21日 星期三

C++ 簡易速查

Virtual Function
虛擬函數


虛擬函數會以關鍵字 virtual 為首宣告在基底類別。用途為供其衍生類別各自實作所需的同名成員函數。

ex.

class MyClassVF {
public:
virtual int myfunc ()
{ return 0; }
};


Pure Virtual Function
單純虛擬函數


為虛擬函數的一種,其宣告方式為 virtual return_type function_declaration (parameter) = 0;

ex.

class MyClassPVF {
public:
virtual int myfunc (void) = 0;
};


Abstract Class
抽象類別


含有虛擬函數宣告的類別即為抽象類別,所以上述面舉的兩個例子中的 MyClassVF、MyClassPVF 都是。

Boxing and Unboxing
裝箱、拆箱


Boxing 將實值類別轉換成 object 類別。
Unboxing 將 object 類別轉換成實值類別。
參考資料:http://msdn.microsoft.com/zh-tw/library/yz2be5wk.aspx

ex.

int i = 123; // a value type
object o = i; // boxing
int j = (int)o; // unboxing


Tracking Handles
追蹤處理


Tracking Handle 有點像是指標,其內容也是存一個位址。
宣告方式為 type^ variable_name;
不過和指標不一樣的是,他的位址是由垃圾回收者自動更新。
換句話說,手動調整 Tracking Handle 的位址是不被允許的。
還有,和指標一樣,在宣告 Tracking Handle 時,他是不指向任何位址的。
因此,任何的參考前都必須先作指定初始位址的動作。

ex.

String^ sentence;
sentence = nullptr; // set handle to null
sentence = "This is a sentence.";

int^ value = 0; // initialization
*value = 100;


L"...."

將 "..." 轉換為 unicode。

stdafx.h

參考文件:http://zhidao.baidu.com/question/3711602.html

Using Enumerators as Flags

一個很實用的技巧,不過只有在 C++/CLI 底下才能用。ANSI C++ 並不支援。
參考資料:Beginning Visual C++ 2008[Ivor Horton]

ex.

[Flags] enum class FlagBits{ Ready = 1, ReadMode = 2, WriteMode = 4, EOF = 8, Disabled = 16};
FlagBits status = FlagBits::Ready | FlagBits::ReadMode | FlagBits::EOF;
Console::WriteLine(L”Current status: {0}”, status);


output:
Current status: Ready, ReadMode, EOF

2009年10月19日 星期一

winsck example

底下是一個簡單的winsck範例
之前雖然在linux上寫過不過為了測試這個也是花了不少時間
環境:win xp, visual studio express
基本上寫程式這種東西....幾個簡單的東西try通之後,靠的就是想像力和組織能力啦

雖說萬事起頭難,不過東拼西湊完之後的測試,花的時間也是不容小覷


#include
#include
#include
#include

#pragma comment(lib, "Wsock32.lib")

#define MAXLINE 1024


int main() {
SOCKET recv_sd, send_sd;
int cli_len, n, sendtoRet, bindRet, errno;
char str[MAXLINE];

struct sockaddr_in recv_addr, send_addr;

WSADATA wsadata;

if (WSAStartup(0x101, (LPWSADATA) &wsadata) != 0) {
fprintf(stderr, "echo_serv: can't use WinSock DLL\n");
exit(1);
}

if ( (recv_sd = socket(AF_INET, SOCK_RAW, 0)) == SOCKET_ERROR) {
fprintf(stderr, "echo_serv: can't open TCP socket\n");
exit(1);
}

if ( (send_sd = socket(AF_INET, SOCK_DGRAM, 0)) == SOCKET_ERROR) {
fprintf(stderr, "echo_serv: can't open UCP socket\n");
exit(1);
}

// set dst address to broadcast
memset(&send_addr, 0, sizeof send_addr);
send_addr.sin_family = AF_INET;
send_addr.sin_port = 1000;
bindRet = bind(send_sd, (struct sockaddr *)&send_addr, sizeof send_addr);

setsockopt( send_sd, SOL_SOCKET, SO_BROADCAST, "TRUE", 4 );

memset(&send_addr, 0, sizeof send_addr);
send_addr.sin_family = AF_INET;
send_addr.sin_port = 68;
send_addr.sin_addr.s_addr = inet_addr("255.255.255.255");

strcpy_s(str, 12, "Hello World");
//while(1)
sendtoRet = sendto(send_sd, str, 12, 0, (struct sockaddr *)&send_addr, sizeof send_addr);

printf("%d", WSAGetLastError());

closesocket(recv_sd);
closesocket(send_sd);

return 0;
}