顯示具有 cplus 標籤的文章。 顯示所有文章
顯示具有 cplus 標籤的文章。 顯示所有文章

2014年4月20日 星期日

c++ static_cast, dynamic_cast, const_cast, reinterpret_cast

最近又稍微碰到這類的問題,想說來複習一下也不錯,這邊有不錯的解說 ,可以參考一下,這篇主要是記錄一下這四種type conversion的方法,基本上一扯到conversion,想當然爾,就會關係到C++裡面有的一個很需要注意的東西,那就是implicit conversion和explicit conversion,所以就先來講這兩個東西,就如同字面上的意思一樣,explicit是明顯的意思,因此explicit conversion
大家都應該很熟悉,就像是...

int i(5.2);

這樣藉由 ( ) 這樣的語法轉換型態,就是明顯的轉換,那麼implicit是隱含的,所以什麼是隱含的轉換呢? 其實大家應該都常常寫到,只是不自覺,所以會很恐怖 :) 像是..

double d = 5.2;
int i = d; //相當於 int i = int(d) 或 (int)d

在你initialize的同時,C++會自動幫你轉換型態 :)
或許這樣一看你會覺得不知道恐怖在哪是吧 :p
的確今天的型態如果只是primitive,那你大概是不用怎麼怕,那如果是自己定義的呢??
舉個例子

#include <iostream>
#include <typeinfo>
using namespace std;


class A
{
public:
    A(int a=0)
    :mx(a)
    {
    }

private:
    int mx;
};

void test(A obj)
{
    cout<<typeid(obj).name()<<endl;
}


int main()
{
   test(2);

   return 0;
}


你將會看到,嘿嘿成功執行,你傳入的參數2,其實已經成為classA的copy constructor的參數了,你也可以看到印出來的type的確也是class A,上面只是跟你說一下,型態轉換在C++上面是很恐怖的,常常在很多你想不到的地方,他就發生了,就像這樣,如果哪個一個不小心,就會造成或許不是你預期的結果 :)

哼哼尤其是在stl中,如果你想用到user defined class且有包含指標型態的話,通常最好要定義一下你的copy constructor,因為大概會被call到。關於這邊改天有心情的話,就來用個例子好啦 :)

該來講一下四種cast的方法,在我上面給的那個連結基本上已經不錯的解說了,所以這邊就簡單總結一下而已

static_cast
可以call implict conversoin和explicit conversion
另外還有upcasting和downcasting
只是他不像dynamic_cast會做動態的檢查

dynamic_cast
負責掌控 upcasting 和 downcasting


const_cast
它可以強制加上或拿掉一個變數的const特性,雖然我不知道這樣的實用在哪就是了 :-S

reinterpret_cast
一個很恐怖的東西,它可以強制轉換型態,任意的轉換,所以不要亂用

另外關於這些cast想要更詳細的,可以看看 這篇  :)

2013年9月25日 星期三

C++ regex

之前看到C++ 11發表那些新特色,就滿懷心喜的想要來嘗試一下,第一個我就嘗試了一下regular expression,因為在python中用的十分爽,簡單易用,結果呢?  讓我又喜又氣! 沒錯你沒看錯,為何我會有這種奇異的感受呢?
這就要請先看看下圖 :)


在visual studio裡面一切事都表現正常的,讓我十分開心,但是悲劇的是,當我開始用code blocks的時候,發現竟然得到的答案是不一樣的!! 竟然是沒有任何match,這讓我非常shock阿,起初我還以為是我regular expression寫錯了,畢竟又不是很常用,搞不好我忘了什麼重要的東西,心裡先這樣安慰自己一下:),但是經過多次嘗試後,仍然一樣,最後我用了python來測試一下,發現,很好,是我要的結果阿! 那到底是錯在哪?


經過我的多次搜尋,我發現因為C++ 11還太過新,目前沒有compiler是能夠完全支援的,但我在網路上看到評分,VS的compiler支援度竟然是最差?,G++反而是最多的,誰知道今天VS反而能夠滿足我= =,而且G++竟然是沒支援,讓我原本滿懷期待的心情都落空了 :( 我真心懷疑那個評分是正確的嗎? 目前,我看大概要用一些新特色的話,就是用boost這個library吧,畢竟有許多C11的特色都是借鏡這個library的,另外,也免的到時候又哪個compiler沒支援你要的特色,都不知道錯在哪了。


最後抱怨一下 :) 要是沒支援好歹也給的錯誤訊息,說你沒支援阿!! 讓我都不知道錯在哪...

2013年9月10日 星期二

vector of pointer to datatype

最近開始回去用C++,乎~真的是久沒用,除了打code時忘了用 ; 來結尾,還有忘了打 { }(因為太習慣python了...),另外對於一些C++ compiler背後運作的方式都有點生疏了,像是一些關於繼承方面會用到的語法xxx: public virtual xxx,虛擬繼承的東西,為啥會有這種東西的存在我不用多說吧? 有興趣就google: c++ diamod problem。


今天是想要記錄一些比較瑣碎的東西,以前我在用std::vector的時候,從來都沒有用資料型態是指標的,所以就沒有注意到一個問題,那就是如下code所示

class animal
{
public:
    animal()
    {
        cout<<"create default"<<endl;
    }

    virtual ~animal()
    {
        cout<<"delete default"<<endl;
    }

};

class dog: public animal
{
public:
    dog()
    {
        cout<<"create dog"<<endl;
    }

    virtual ~dog()
    {
        cout<<"delete dog"<<endl;
    }
};


class cat:public animal
{
public:
    cat()
    {
        cout<<"create cat"<<endl;
    }

    virtual ~cat()
    {
        cout<<"delete cat"<<endl;
    }
};



int main()
{
    vector<animal*> obj;
    obj.push_back(new cat());
    obj.push_back(new dog());


    //vector<animal*>::iterator
    //sintax sugar auto
    for(auto it=obj.begin(); it!=obj.end(); ++it)
    {
        delete *it;
    }
    cout<<"..."<<endl;
    return 0;
}

今天我宣告一個baseclass名為animal,然後有兩個class去繼承他分別為cat和dog,用這樣是為了來做一個upcasting的例子而已,其實這樣的做法是有其方便的地方,假如你今天在做一個遊戲,想當然爾需要常常用到Draw(...)來render物件吧,那麼這時候upcasting這種方式就可以出來耀武揚威了:) 你可以宣告一個interface裡面有draw(),然後繼承該class的class也必須分別implement它們各自的Draw的內容,那麼接下來你就可以用
vector<xxx*> obj
for(.......)
{
    obj->draw();
}

其實今天想要說的東西是,當你用vector<xxx>,xxx這是指標型態的時候,千萬要記得事後自己要delete掉,像我上面code那樣,vector只是幫你handle那些指標占掉的空間,而不會幫你清掉你new的東西,不信你就把我用來delete的那行去掉,看看程式執行會不會有跑出delete的訊息。

第二件想要記錄的是,C++11有個關鍵字叫auto,感覺真棒,一個很棒的sintax sugar,雖然沒有這東西,你也可以用typedef來達到類似功能,只是直接用auto是更爽的一件事 :)

2013年8月5日 星期一

how to write a dll

dynamic link library(dll) 這是在windows上的稱呼,至於linux的稱呼是 shared library,沒記錯的話應該是這樣沒錯。最近想嘗試用python去call自己寫的dll檔,所以就開始學習如何產生dll檔。

 經過我的嘗試後,發現dll的使用方式有兩種
  1. load-time dynamic linking (個人喜歡稱 implicity load way
  2. run-time dynamic linking ( explicit load way

為何會這樣稱呼呢? 我想在稍後或許你就會了解了。
首先寫一個dll檔,它也是有所謂的entry point的,就像是用C++和C寫一個console介面的程式,main就是entry point,win32則是WinMain。
BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
{
    return TRUE;
}
我對這個entry point實際上可以做哪些還不是很清楚,依照我看到的資料是說可以在這邊做一些資料的初始化和釋放,但是這個entry point可有可無並沒有強制規定要存在,所以目前我就沒有多去了解了。

再來就是有個key word要注意了 __declspec() 這個可接受的參數有很多,但是目前我僅用到兩個
  1. dllexport
  2. dllimport
假設今天我寫了一個這樣的函式我想要讓別人用dll可以call它,就要這樣寫
extern "C" __declspec(dllexport) int multipleByTwo(int num=2)
{
    std::cout<<"num will be multipled by 2"<<std::endl;
    return num*2;
}
這樣一來被編譯成dll後,在另外一個檔案要用到這函式呢,就要如下面這樣寫,先做個宣告
extern "C" __declspec(dllimport) int multipleByTwo(int num);
宣告之後呢~嘿嘿還記得前面提到的兩種方式嗎?這個方法是implicity way,因為呢,這樣宣告後必須還要link library檔才有辦法編譯成功,要不然就會跑出錯誤提示找不到該函式的reference,另外dll也必須在執行檔的同個目錄喔! 要不然在run time的時候就會錯誤了。另外像這種宣告都會把它放在header file就是了。

至於 explicity way呢,就是用到了LoadLibrary("xxx.dll")這種函式,明顯的去load dll檔,這種方法就不需要像前面那樣link library和宣告 __declspec(dllimport),只是你相對就要去寫一些LoadLibrary和GetProcAddress之類的東西,不過這種的方式我就沒去嘗試了。

不過因為目前我只是測試如何產生dll檔,所以就沒有特別去講究結構了 :) 之後就是來繼續做深入一點的研究,有心得後再上來PO

2013年7月22日 星期一

c++ traits

今天逛一些論壇,意外發現到我以前學C++都沒有注意過的技術" C++ traits"
我是看到這篇的解說 http://www.cantrip.org/traits.html 讓我重新知道自己似乎該是時候回到C++的懷抱了:) 之前學了一些,但是自從用了python,就一直很少回去碰C++,如今感覺,該是時候繼續精進C++了。

這個技術目前我覺得只是對於template遇到某些型態對此特別處理這樣,讓泛型的樣板,更加容易使用,更加靈活,看完這篇論述後,心裡有了一點想法,可以使用traits來進行參數的型態判斷,code如下

#include<iostream>
using namespace std;

template<typename T>
class typeof
{
    public:
        const char *type = "unknown";
};

template<>
class typeof<char>
{
    public:
        const char *type = "char";
};

template<>
class typeof<int>
{
    public:
        const char *type = "int";
};

template<typename T, typename C=typeof<T>>
class test
{
    public:
        test()
        {
            C obj;
            cout<<obj.type<<endl;
        }
};

int main()
{
    test<int> a;
    test<char> b;
    test<bool> c;
    return 0;
}

結果如圖:

結果果然如我所想一樣 :) 當然traits我現在其實也不是完全很瞭啦,畢竟剛看沒多久,另外沒想到C++ 11 竟然支援 class在宣告資料的同時也可以進行initialize,嚇到我了! 看來在我沒用C++的時期,C++改變了很多阿!!! 真的要找時間好好重新認識C++了 :)