模板編譯器
❶ 公眾號模板編輯器有哪些啊
推薦微小寶編輯器,現在網路上的編輯器各式各樣,有微小寶,135,秀米,西瓜等等,微小寶的功能豐富,素材更多,操作方便。135做的比較細,功能不夠齊全,西瓜是收費,秀米適合H5頁面製作,在不考慮做H5頁面的情況下,我個人一般使用微小寶居多,比較免費,還有素材。
❷ 為什麼C++編譯器不能支持對模板的分離式編譯
當編譯器將一個工程里的所有.cpp文件以分離的方式編譯完畢後,再由連接器(linker)進行連接成為一個.exe文件。 舉個例子: //---------------test.h-------------------//void f();//這里聲明一個函數f //---------------test.cpp--------------//#include」test.h」void f(){…//do something} //這里實現出test.h中聲明的f函數 //---------------main.cpp--------------//#include」test.h」int main(){f(); //調用f,f具有外部連接類型} 在這個例子中,test. cpp和main.cpp各自被編譯成不同的.obj文件(姑且命名為test.obj和main.obj),在main.cpp中,調用了f函數,然而當編譯器編譯main.cpp時,它所僅僅知道的只是main.cpp中所包含的test.h文件中的一個關於void f();的聲明,所以,編譯器將這里的f看作外部連接類型,即認為它的函數實現代碼在另一個.obj文件中,本例也就是test.obj,也就是說,main.obj中實際沒有關於f函數的哪怕一行二進制代碼,而這些代碼實際存在於test.cpp所編譯成的test.obj中。在main.obj中對f的調用只會生成一行call指令,像這樣: call f [C++中這個名字當然是經過mangling[處理]過的] 在編譯時,這個call指令顯然是錯誤的,因為main.obj中並無一行f的實現代碼。那怎麼辦呢?這就是連接器的任務,連接器負責在其它的.obj中(本例為test.obj)尋找f的實現代碼,找到以後將call f這個指令的調用地址換成實際的f的函數進入點地址。需要注意的是:連接器實際上將工程里的.obj「連接」成了一個.exe文件,而它最關鍵的任務就是上面說的,尋找一個外部連接符號在另一個.obj中的地址,然後替換原來的「虛假」地址。 這個過程如果說的更深入就是: call f這行指令其實並不是這樣的,它實際上是所謂的stub,也就是一個jmp 0xABCDEF。這個地址可能是任意的,然而關鍵是這個地址上有一行指令來進行真正的call f動作。也就是說,這個.obj文件裡面所有對f的調用都jmp向同一個地址,在後者那兒才真正」call」f。這樣做的好處就是連接器修改地址時只要對後者的call XXX地址作改動就行了。但是,連接器是如何找到f的實際地址的呢(在本例中這處於test.obj中),因為.obj與.exe的格式是一樣的,在這樣的文件中有一個符號導入表和符號導出表(import table和export table)其中將所有符號和它們的地址關聯起來。這樣連接器只要在test.obj的符號導出表中尋找符號f(當然C++對f作了mangling)的地址就行了,然後作一些偏移量處理後(因為是將兩個.obj文件合並,當然地址會有一定的偏移,這個連接器清楚)寫入main.obj中的符號導入表中f所佔有的那一項即可。 這就是大概的過程。其中關鍵就是: 編譯main.cpp時,編譯器不知道f的實現,所以當碰到對它的調用時只是給出一個指示,指示連接器應該為它尋找f的實現體。這也就是說main.obj中沒有關於f的任何一行二進制代碼。 編譯test.cpp時,編譯器找到了f的實現。於是乎f的實現(二進制代碼)出現在test.obj里。 連接時,連接器在test.obj中找到f的實現代碼(二進制)的地址(通過符號導出表)。然後將main.obj中懸而未決的call XXX地址改成f實際的地址。完成。 然而,對於模板,你知道,模板函數的代碼其實並不能直接編譯成二進制代碼,其中要有一個「實例化」的過程。舉個例子: //----------main.cpp------//template<class T>void f(T t){} int main(){…//do somethingf(10); // call f<int> 編譯器在這里決定給f一個f<int>的實例…//do other thing} 也就是說,如果你在main.cpp文件中沒有調用過f,f也就得不到實例化,從而main.obj中也就沒有關於f的任意一行二進制代碼!如果你這樣調用了: f(10); // f<int>得以實例化出來f(10.0); // f<double>得以實例化出來 這樣main.obj中也就有了f<int>,f<double>兩個函數的二進制代碼段。以此類推。 然而實例化要求編譯器知道模板的定義,不是嗎? 看下面的例子(將模板的聲明和實現分離): //-------------test.h----------------//template<class T>class A{public:void f(); // 這里只是個聲明}; //---------------test.cpp-------------//#include」test.h」template<class T>void A<T>::f() // 模板的實現{ …//do something} //---------------main.cpp---------------//#include」test.h」int main(){A<int> a;f(); // #1} 編譯器在#1處並不知道A<int>::f的定義,因為它不在test.h裡面,於是編譯器只好寄希望於連接器,希望它能夠在其他.obj裡面找到A<int>::f的實例,在本例中就是test.obj,然而,後者中真有A<int>::f的二進制代碼嗎?NO!!!因為C++標准明確表示,當一個模板不被用到的時侯它就不該被實例化出來,test.cpp中用到了A<int>::f了嗎?沒有!!
❸ C++模板程序為什麼通不過編譯
在31行處,將deletememory(); 改為deletememory(strack)就可以了,我的編譯環境:linux,G++,命令:G++ 1.c -o 1.o
❹ C++模板與宏的問題
常用宏定義
1、防止一個頭文件被重復包含
#ifndef COMDEF_H
#define COMDEF_H
//頭文件內容
#endif
2、重新定義一些類型,防止由於各種平台和編譯器的不同,而產生的類型位元組數差異,方便移植。
typedef unsigned char boolean; /* Boolean value type. */
typedef unsigned long int uint32; /* Unsigned 32 bit value */
typedef unsigned short uint16; /* Unsigned 16 bit value */
typedef unsigned char uint8; /* Unsigned 8 bit value */
typedef signed long int int32; /* Signed 32 bit value */
typedef signed short int16; /* Signed 16 bit value */
typedef signed char int8; /* Signed 8 bit value */
//下面的不建議使用
typedef unsigned char byte; /* Unsigned 8 bit value type. */
typedef unsigned short word; /* Unsinged 16 bit value type. */
typedef unsigned long dword; /* Unsigned 32 bit value type. */
typedef unsigned char uint1; /* Unsigned 8 bit value type. */
typedef unsigned short uint2; /* Unsigned 16 bit value type. */
typedef unsigned long uint4; /* Unsigned 32 bit value type. */
typedef signed char int1; /* Signed 8 bit value type. */
typedef signed short int2; /* Signed 16 bit value type. */
typedef long int int4; /* Signed 32 bit value type. */
typedef signed long sint31; /* Signed 32 bit value */
typedef signed short sint15; /* Signed 16 bit value */
typedef signed char sint7; /* Signed 8 bit value */
3、得到指定地址上的一個位元組或字
#define MEM_B( x ) ( *( (byte *) (x) ) )
#define MEM_W( x ) ( *( (word *) (x) ) )
4、求最大值和最小值
#define MAX( x, y ) ( ((x) > (y)) ? (x) : (y) )
#define MIN( x, y ) ( ((x) < (y)) ? (x) : (y) )
5、得到一個field在結構體(struct)中的偏移量
#define FPOS( type, field ) \
/*lint -e545 */ ( (dword) &(( type *) 0)-> field ) /*lint +e545 */
6、得到一個結構體中field所佔用的位元組數
#define FSIZ( type, field ) sizeof( ((type *) 0)->field )
7、按照LSB格式把兩個位元組轉化為一個Word
#define FLIPW( ray ) ( (((word) (ray)[0]) * 256) + (ray)[1] )
8、按照LSB格式把一個Word轉化為兩個位元組
#define FLOPW( ray, val ) \
(ray)[0] = ((val) / 256); \
(ray)[1] = ((val) & 0xFF)
9、得到一個變數的地址(word寬度)
#define B_PTR( var ) ( (byte *) (void *) &(var) )
#define W_PTR( var ) ( (word *) (void *) &(var) )
10、得到一個字的高位和低位位元組
#define WORD_LO(xxx) ((byte) ((word)(xxx) & 255))
#define WORD_HI(xxx) ((byte) ((word)(xxx) >> 8))
11、返回一個比X大的最接近的8的倍數
#define RND8( x ) ((((x) + 7) / 8 ) * 8 )
12、將一個字母轉換為大寫
#define UPCASE( c ) ( ((c) >= 'a' && (c) <= 'z') ? ((c) - 0x20) : (c) )
13、判斷字元是不是10進值的數字
#define DECCHK( c ) ((c) >= '0' && (c) <= '9')
14、判斷字元是不是16進值的數字
#define HEXCHK( c ) ( ((c) >= '0' && (c) <= '9') ||\
((c) >= 'A' && (c) <= 'F') ||\
((c) >= 'a' && (c) <= 'f') )
15、防止溢出的一個方法
#define INC_SAT( val ) (val = ((val)+1 > (val)) ? (val)+1 : (val))
16、返回數組元素的個數
#define ARR_SIZE( a ) ( sizeof( (a) ) / sizeof( (a[0]) ) )
17、返回一個無符號數n尾的值MOD_BY_POWER_OF_TWO(X,n)=X%(2^n)
#define MOD_BY_POWER_OF_TWO( val, mod_by ) \
( (dword)(val) & (dword)((mod_by)-1) )
18、對於IO空間映射在存儲空間的結構,輸入輸出處理
#define inp(port) (*((volatile byte *) (port)))
#define inpw(port) (*((volatile word *) (port)))
#define inpdw(port) (*((volatile dword *)(port)))
#define outp(port, val) (*((volatile byte *) (port)) = ((byte) (val)))
#define outpw(port, val) (*((volatile word *) (port)) = ((word) (val)))
#define outpdw(port, val) (*((volatile dword *) (port)) = ((dword) (val)))
19、使用一些宏跟蹤調試
ANSI標准說明了五個預定義的宏名。它們是:
__LINE__
__FILE__
__DATE__
__TIME__
__STDC__
C++中還定義了 __cplusplus
如果編譯器不是標準的,則可能僅支持以上宏名中的幾個,或根本不支持。記住編譯程序也許還提供其它預定義的宏名。
__LINE__ 及 __FILE__ 宏指示,#line指令可以改變它的值,簡單的講,編譯時,它們包含程序的當前行數和文件名。
__DATE__ 宏指令含有形式為月/日/年的串,表示源文件被翻譯到代碼時的日期。
__TIME__ 宏指令包含程序編譯的時間。時間用字元串表示,其形式為: 分:秒
__STDC__ 宏指令的意義是編譯時定義的。一般來講,如果__STDC__已經定義,編譯器將僅接受不包含任何非標准擴展的標准C/C++代碼。如果實現是標準的,則宏__STDC__含有十進制常量1。如果它含有任何其它數,則實現是非標準的。
__cplusplus 與標准c++一致的編譯器把它定義為一個包含至少6為的數值。與標准c++不一致的編譯器將使用具有5位或更少的數值。
可以定義宏,例如:
當定義了_DEBUG,輸出數據信息和所在文件所在行
#ifdef _DEBUG
#define DEBUGMSG(msg,date) printf(msg);printf(「%d%d%d」,date,_LINE_,_FILE_)
#else
#define DEBUGMSG(msg,date)
#endif
20、宏定義防止錯誤使用小括弧包含。
例如:
有問題的定義:#define DUMP_WRITE(addr,nr) {memcpy(bufp,addr,nr); bufp += nr;}
應該使用的定義: #difne DO(a,b) do{a+b;a++;}while(0)
例如:
if(addr)
DUMP_WRITE(addr,nr);
else
do_somethong_else();
宏展開以後變成這樣:
if(addr)
{memcpy(bufp,addr,nr); bufp += nr;};
else
do_something_else();
gcc 在碰到else前面的「;」時就認為if語句已經結束,因而後面的else不在if語句中。而採用do{} while(0)的定義,在任何情況下都沒有問題。而改為 #difne DO(a,b) do{a+b;a++;}while(0) 的定義則在任何情況下都不會出錯。
❺ 自己可以做96編輯器模板嗎
可以做九六編輯器模擬版嗎?如果自己會的話,就可以做呀
❻ C++模板類實例化,編譯器報錯
第一種方法意味著在使用模板的轉換文件中不但要包含模板聲明文件,還要包含模板定義文件。在上例中,就是第一個示例,在array.h中用行內函數定義了所有的成員函數。或者在main.cpp文件中也包含進array.cpp文件。這樣編譯器就能看到模板的聲明和定義,並由此生成array<int, 50>實例。這樣做的缺點是編譯文件會變得很大,顯然要降低編譯和鏈接速度。
第二種方法,通過顯式的模板實例化得到類型。最好將所有的顯式實例化過程安放在另外的文件中。在本例中,可以創建一個新文件templateinstantiations.cpp:
// templateinstantiations.cpp
#include "array.cpp"
template class array <int, 50>; // 顯式實例化
❼ 為什麼輸出是123為什麼編譯器會使用模板求大神詳細解答
「123」與"321"是常量字元串,類型是const char *。在編譯器看來這與char *是兩種區別,而不是單純的內訪問控制屬性不同。容所以不會跟你的字元串比較函數匹配。
PS:有時候之所以這兩種類型能互換是因為有隱性類型轉換這樣的機制而已
❽ 下面是一個模板類的友元類,我用的編譯器是vc 6.0
//我也剛好遇到類似的問題,以前遇到都放棄了,遇到你也有同樣的問題,
//幾經搜索,終於得到答案,共勉!(VC++6.0下通過!)
#include <iostream>
using namespace std;
template<class T> class v2;//將這里最後的"<T>"去掉即可!
template<class Type>
class v1
{
public:
friend class v2<Type>;
private:
int a;
};
template<class T>
class v2
{
private:
T b;
};
int main()
{
return 0;
}
❾ 模板類無法編譯通過,誰能幫我解釋
返回值前面加個 typename就可以,
這是為了告訴編譯器class_A<T>::struct_A是一種類型而不是類的成員變數
其實:
warning C4346: 「class_A<T>::struct_A」 : 依賴名稱不是類型
用「typename」為前綴來表示類型
編譯器說的非常明確了!
VS7.1上編譯通過!VS6.0不知道可不可以!
template <class T>
typename class_A<T>::struct_A* //---這里加個typename
class_A<T>::generate_new_struct_A_instance()
{
struct_A * new_instance = new struct_A;
new_instance->a = 1;
new_instance->b = 2;
return new_instance;
}
///
改成double 為什麼可以,我很長時間沒看模板了,具體我也不清楚!
我估計對於特化的函數是把它當作一般函數那樣編譯的!