C++易混知識點2. 函數指針和指針函數的區別

我們時常在C++開發中用到指針,指針的好處是開銷很小,可以很方便的用來實現想要的功能,當然,這裏也要涉及到指針的一些基本概念。指針不是基本數據類型,我們可以理解他爲一種特殊類型的對象,他佔據一定空間,但是所帶來的好處就是C++如此強大的深層次原因了。


轉載請註明出處: http://blog.csdn.net/elfprincexu


1. 指針函數, ( __type__ * func( void, int,) )


顧名思義,他是一個函數,只不過和一般函數區分的原因是它返回的是一個指針。

int* f ( int , int ) ; // 返回的是一個整形指針

int  f ( int, int);// 返回的是一個整形數


上面兩個區別的僅僅是返回值得不同,(注意順便說下,返回值不同可不是重載函數,重載函數只根據形參的類型和個數,當然,只讀函數const也是重載函數的判斷依據)


當然,指針函數在使用時,必須與調用者的類型相同, 也就是說,返回值必須和左值的類型相同。

int * a = f (5,67) ; // 合法,類型相同


總結: 指針函數,比較容易懂,和一般函數的區別僅僅是返回值得不同,調用時注意返回的類型指針。


2. 函數指針 (__type__ (* func)(void*, int))

函數指針,顧名思義,還是一個指針,只不過這個指針比較特殊,他和其他函數名一樣,具有(返回值類型,形參個數和類型)

int (*pFunc) (int , float) ;  // 合法,定義了一個函數指針pFunc,該函數指針具有 返回int類型,同時帶有兩個形參,一個是int, 另一個是float;

我們可以簡單理解爲函數指針和一般的函數名一樣,其實,一般情況下,函數名所代表的含義就是一個函數入口地址(指針)。 

int getSum (int a, float b);

pFunc = getSum;//合法,函數名也可以理解爲指針

pFunc = &getSum; // 合法,& 去地址符可以省略

int x = (*pFunc)(3,50;// 合法,使用函數指針調用時,我們需要用掛號將它包圍使用,


void (*funcp)();
        void FileFunc(),EditFunc();
        main()
        {
            funcp=FileFunc;
            (*funcp)();
            funcp=EditFunc;
            (*funcp)();
        }
        void FileFunc()
        {
            printf(FileFunc\n);
        }
        void EditFunc()
        {
            printf(EditFunc\n);
        }
        程序輸出爲:
            FileFunc
            EditFunc


總結: 函數指針,本質是指針,不過代表的是一個函數入口地址,我們可以用該指針靈活的使用不同的函數。


在一般情況下,函數指針比較常用,他可以靈活的使用不同的函數來實現我們想要的結果。比如在常見的C++應用中,我們往往會定義一個函數指針,該函數指針通過繼承來實現不同的實現。

	class ThreadUser
	{	
		public:
		typedef void (ThreadUser::*EntryPtr)(void * arg)	;// 定義了一個函數指針EntryPtr, 參數爲無類型指針,返回值爲空值void
	}

	class Thread
	{
		public:
		Thread(ThreadUser&, ThreadUser::EntryPtr, void* arg = 0 );
		...

		private:
		pthread_t _thread;
		pthread_attr_t _threadAtrributes;
		Thread::EntryPt	_entry;
		ThreadUser*	_user;
		bool 	_done; void * _arg;
		static void entry(Thread&);// 線程入口函數
		static int _threadCount;
	}
定義:
	typedef void* (*EntryPoint)(void*); // 定義另一個函數指針,爲pthread_create服務,pthread_create 線程入口函數start_rtn需要此類型函數
	Thread::Thread(ThreadUser& u, ThreadUser::EntryPtr e, void* arg ) : _entry(e), _user(&u), _done(false), _arg(arg) 
	{
		memset (&_thread, 0, sizeof (_thread);
		memset(&_threadAttributes, 0, sizeof (_threadAttributes);
		int thrCreateResult;
		if ((thrCreateResult = pthread_create(&_thread,&_threadAttributes, (EntryPoint)entry, this)) != 0) // this 作爲入口函數的argu
		{
			cerr << "pthread_create failed " << errno << endl;
		}
		else 
		{
			_started = true;
			_threadCount ++;
		}
		return true;
	}

	void Thread::entry(Thread& t)// 入口函數,形參爲Thread 對象,在上面this
	{
		(t._user->*t._entry)(t._arg);			// 調用該函數指針所指向的函數
		t._done = true;
	}






發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章