熟練掌握C/C++語言,熟悉Windows開發(fā)平臺,能熟練運用MFC自主編開發(fā)出一些應(yīng)用程序;
熟練掌握SQL語句,對數(shù)據(jù)庫有很好的認識,能熟練使用SQL Server2000軟件;
熟練掌握JAVA語言,熟悉J2ME對手機軟件開發(fā)一定的基礎(chǔ);
深入理解面向?qū)ο蟮乃枷?,并能熟練?yīng)用于具體的程序設(shè)計開發(fā)中;
熟悉Unix/Linux下C語言的編程以及常用的命令,熟悉匯編語言;
熟悉網(wǎng)絡(luò)的TCP/IP、UDP等協(xié)議,能處理解決電腦系統(tǒng)軟件常見的故障;
C++ using namespace std 詳解
所謂namespace,是指標(biāo)識符的各種可見范圍。C++標(biāo)準(zhǔn)程序庫中的所有標(biāo)識符都被定義于一個名為std的namespace中。
一 :
和是不一樣,前者沒有后綴,實際上,在你的編譯器include文件夾里面可以看到,二者是兩個文件,打開文件就會發(fā)現(xiàn),里面的代碼是不一樣的。
后綴為.h的頭文件c++標(biāo)準(zhǔn)已經(jīng)明確提出不支持了,早些的實現(xiàn)將標(biāo)準(zhǔn)庫功能定義在全局空間里,聲明在帶.h后綴的頭文件里,c++標(biāo)準(zhǔn)為了和C區(qū)別開,也為了正確使用命名空間,規(guī)定頭文件不使用后綴.h。
因此,當(dāng)使用時,相當(dāng)于在c中調(diào)用庫函數(shù),使用的是全局命名空間,也就是早期的c++實現(xiàn);當(dāng)使用的時候,該頭文件沒有定義全局命名空間,必須使用namespacestd;這樣才能正確使用cout。
二:
所謂namespace,是指標(biāo)識符的各種可見范圍。
C++標(biāo)準(zhǔn)程序庫中的所有標(biāo)識符都被定義于一個名為std的namespace中。
由于namespace的概念,使用C++標(biāo)準(zhǔn)程序庫的任何標(biāo)識符時,可以有三種選擇:
1、直接指定標(biāo)識符。例如std::ostream而不是ostream。完整語句如下:
std::cout<<std::hex<<3.4<< std::endl;
2、使用using關(guān)鍵字。
using std::cout;
using std::endl;
以上程序可以寫成
cout <<std::hex<<3.4<< endl;
3、最方便的就是使用using namespacestd;
例如:
#include
#include
#include
using namespace std;
這樣命名空間std內(nèi)定義的所有標(biāo)識符都有效(曝光)。就好像它們被聲明為全局變量一樣。那么以上語句可以如下寫:
cout <<hex<<3.4<< endl;
因為標(biāo)準(zhǔn)庫非常的龐大,所程序員在選擇的類的名稱或函數(shù)名時就很有可能和標(biāo)準(zhǔn)庫中的某個名字相同。所以為了避免這種情況所造成的名字沖突,就把標(biāo)準(zhǔn)庫中的一切都被放在名字空間std中。但這又會帶來了一個新問題。無數(shù)原有的C++代碼都依賴于使用了多年的偽標(biāo)準(zhǔn)庫中的功能,他們都是在全局空間下的。
所以就有了和等等這樣的頭文件,一個是為了兼容以前的C++代碼,一個是為了支持新的標(biāo)準(zhǔn)。
命名空間std封裝的是標(biāo)準(zhǔn)程序庫的名稱,標(biāo)準(zhǔn)程序庫為了和以前的頭文件區(qū)別,一般不加".h"
using namespace std 的用法
摘自
usingnamespacestd;用的并不少!
---------------------------------------------------------------
實際上就是告訴編譯器,你類型是什么,在哪能找到。
常用的是using namespacestd,就是說用C++的標(biāo)準(zhǔn)名字空間。
你也可以引用你自己的名字空間。比如說:
import "C:\MyTest\test.tlb"
using namespace CMyTest
就可以引用CMyTest內(nèi)的各個類型名
看C++ prime
---------------------------------------------------------------
聲明該文件使用C++標(biāo)準(zhǔn)庫吧!
比如
#include
using namespace std;
void main()
{
cout<<"hello!"<< endl;
}
如果不用using namespace std;這句,那么
std::cout <<"hello!"<<endl;
這是名字空間的問題!具體參看有關(guān)書籍吧,新版的C++ 書應(yīng)該都有介紹的!
---------------------------------------------------------------
using 指示符!
這是個名字空間問題,是標(biāo)準(zhǔn)C++引入的新概念!
具體在《C++Primer》第8.6節(jié)有詳細說明!
---------------------------------------------------------------
因為標(biāo)準(zhǔn)庫非常的龐大,所程序員在選擇的類的名稱或函數(shù)名時就很有可能和標(biāo)準(zhǔn)庫中的某個名字相同。所以為了避免這種情況所造成的名字沖突,就把標(biāo)準(zhǔn)庫中的一切都被放在名字空間std中。但這又會帶來了一個新問題。無數(shù)原有的C++代碼都依賴于使用了多年的偽標(biāo)準(zhǔn)庫中的功能,他們都是在全局空間下的。
所以就有了和等等這樣的頭文件,一個是為了兼容以前的C++代碼,一個是為了支持新的標(biāo)準(zhǔn)。
---------------------------------------------------------------
名字空間,實質(zhì)上也是為了方便程序在不同平臺上正確的運行。
---------------------------------------------------------------
namespace是為了解決C++中的名字沖突而引入的。
什么是名字沖突呢?比如,在文件x.h中有個類MyClass,
在文件y.h中也有個類MyClass,而在文件z.cpp中要同時
引用x.h和y.h文件。顯然,按通常的方法是行不能的,
那怎么辦呢?引入namespace即可。例如:
在x.h中的內(nèi)容為
// x.h
namespace MyNamespace1
{
classMyClass
{
public:
voidf();
private:
intm;
}
};
在y.h中的內(nèi)容為
// y.h
namespace MyNamespace2
{
classMyClass
{
public:
voidf();
private:
intm;
}
};
然后在z.cpp中引入x.h和y.h
// z.cpp
#include"x.h"
#include"y.h"
void z::f()
{
//聲明一個文件x.h中類MyClass的實例x
MyNamespace1::MyClassx;
//聲明一個文件x.h中類MyClass的實例x
MyNamespace2::MyClassy;
//調(diào)用文件x.h中的函數(shù)f
x.f();
//調(diào)用文件y.h中的函數(shù)f
y.f();
}
名字空間實質(zhì)上是一個作用域。
通過上面的一個實例應(yīng)該知道名字空間的作用了吧
盡量不要使用using namespacestd;VC++2005使用有感
Posted on 2007-11-06 20:28 Samson小天 閱讀(1163) 評論(6) 編輯 收藏網(wǎng)摘所屬分類:C++/C++.net
今天用了VISUAL C++寫了個小程序(VS2005),很簡單很簡單的,但是就是編譯不通過
出現(xiàn)一個奇怪的問題:錯誤 1 error C2668: “max”: 對重載函數(shù)的調(diào)用不明確
最初代碼如下
#include
using namespace std;
template
T max (T a,T b)
{
return ((a>b)?a:b);
}
void main()
{
double x,y;
cin>>x>>y;
cout<<"Max numberis"<<(max(x,y))<<endl;
cin>>x;
}
我將這段代碼放到VC++6.0下竟然通過了,程序運行也正常。這讓我百思不得其解。后來終于弄明白了!
其實在std命名空間下還有一個MAX函數(shù),而且實現(xiàn)的功能也是一樣的……我昏。利用轉(zhuǎn)到定義功能可以看到微軟是怎么寫MAX函數(shù)的。這里為了不被鄙視就不貼微軟的代碼了。
明白了為什么出現(xiàn)這個錯誤我們就改寫代碼如下:
#include
using std::cin;
using std::cout;
using std::endl;
template
T max (T a,T b)
{
return ((a>b)?a:b);
}
int main()
{
double x,y;
cin>>x>>y;
cout<<"Max numberis"<<(max(x,y))<<endl;
cin>>x;
}
這是我比較推薦的做法,因為C++PRIMER, EFFECTIVE C++上都是用這種方式的,但是譚浩強的書上都是一句usingnamespacestd;就搞定,我覺得蠻簡潔的就一直用了,沒想到帶來那么多的問題,以前在友元函數(shù)上還碰到莫名的錯誤呢。
其實還有兩個簡單的解決方案,那就是把自己定義的函數(shù)改成其他的名字,或者直接用微軟提供的函數(shù)。相信微軟提供的效率絕對不會比我們寫的低~
好了,就寫到這了。希望大家養(yǎng)成良好的編程習(xí)慣,^-^
很多C++程序員還在使用而不是用更新的標(biāo)準(zhǔn)的庫。
這兩者都有什么不同呢?首先,5年前我們就開始反對把.h符號繼續(xù)用在標(biāo)準(zhǔn)的頭
文件中。繼續(xù)使用過時的規(guī)則可不是個好的方法。從功能性的角度來講,
包含了一系列模板化的I/O類,相反地只僅僅是支持字符
流。另外,輸入輸出流的C++標(biāo)準(zhǔn)規(guī)范接口在一些微妙的細節(jié)上都已改進,因此,
和在接口和執(zhí)行上都是不同的。最后,的各組
成都是以STL的形式聲明的,然而的各組成都是聲明成全局型的。
因為這些實質(zhì)上的不同,你不能在一個程序中混淆使用這兩個庫。做為一種習(xí)
慣,在新的代碼中一般使用,但如果你處理的是過去編寫的代碼,為了
繼承可以用繼續(xù)用舊保持代碼的一致性。
///////////////////
表示你使用的是標(biāo)注命名空間,也就是在程序開始應(yīng)該有這么一句話
using namespace std ;
這是遵循c++標(biāo)準(zhǔn)的
則沒有遵循c++標(biāo)準(zhǔn)
////////////////
是舊的C頭文件,對應(yīng)的是基于char*的字符串處理函數(shù);
是包裝了std的C++頭文件,對應(yīng)的是新的strng類;
是對應(yīng)舊的C頭文件的std版本。
在C++語言編寫的程序中,變量和函數(shù)等的作用范圍是有一定限制的。比如,在函數(shù)體中定義的一個臨時變量就不可以在函數(shù)體外使用。為了解決變量和函數(shù)等的作用范圍,在C++語言中引入了名空間的概念,并增加了關(guān)鍵字namespace和using
在一個名空間中可以定義一組變量和函數(shù),這些變量和函數(shù)的作用范圍一致,可以將這些變量和函數(shù)稱為這個名空間的成員。
通過名空間,可以在同一個文件中使用相同的變量名或函數(shù)名,只要它們屬于不同的名空間。另外,名空間可以使得代碼操作具有相同名字但屬于不同庫的變量。而且,名空間也可以提高C語言與C++語言的兼容性。
下面通過例程說明關(guān)鍵字namespace的用法。
#include
#include
namespacecar//名空間的定義
{
intmodel;
intlength;
intwidth;
}
namespaceplane
{
intmodel;
namespacesize//名空間的嵌套
{
intlength;
intwidth;
}
}
namespacecar//添加名空間的成員
{
char*name;
}
namespacec=car;//定義名空間的別名
intTime;//外部變量屬于全局名空間
voidmain()
{
car::length=3;
//下面一句錯誤,故屏蔽掉
//width=2;//對于非全局變量和當(dāng)前有效臨時變量應(yīng)該指定名空間
plane::size::length=70;
cout<<"thelengthofplaneis"<<plane::size::length<<"m."<<endl;
cout<<"thelengthofcaris"<<car::length<<"m."<<endl;
//使用名空間的別名
cout<<"thelengthofcis"<<c::length<<"m."<<endl;
intTime=1996;//臨時變量,應(yīng)區(qū)別于全局變量
::Time=1997;
cout<<"TempTimeis"<<Time<<endl;
cout<<"OuterTimeis"<<::Time<<endl;
//使用關(guān)鍵字using
usingnamespaceplane;
model=202;
size::length=93;
cout<<model<<endl;
cout<<size::length<<endl;
getch();
}
運行結(jié)果:
thelengthofplaneis70m.
thelengthofcaris3m.
thelengthofcis3m.
TempTimeis1996
OuterTimeis1997
說明:
•從上面可以看出,名空間定義了一組變量和函數(shù),它們具有相同的作用范圍。對于不同的
名空間,可以定義相同的變量名或函數(shù)名,在使用的時候,只要在變量名或函數(shù)名前區(qū)分
開不同的名空間就可以了。
•名空間可以被嵌套定義,使用時要逐級對成員用名空間限定符::來引用。
•系統(tǒng)默認有一個全局名空間,它包含了所有的外部變量。這個名空間沒有名字,引用這個
名空間里的變量時要使用名空間限定符::,前面沒有名字。在不使用名空間的情況下,我
們知道,不可以在不同文件中定義相同名字的外部變量,這是因為它們屬于同一個全局名
空間,名字不可以重復(fù)。
•可以給名空間取一個別名。一般別名是一個比較短的名字,來簡化編程。
•在原有定義好的名空間的基礎(chǔ)上,隨時可以往里增加成員。
<<using>>
在前面的例程中可以看到,為了使用時的方便,又引入了關(guān)鍵字using。利用using聲明可以在引用名空間成員時不必使用名空間限定符::。此外,關(guān)鍵字namespace和using的使用,對函數(shù)重載有一定的影響。
下面通過例程進行具體說明。
#include
#include
namespacecar//名空間的定義
{
voidShowLength(doublelen)//參數(shù)類型為double
{
cout<<"incarnamespace:"<<len<<endl;
}
}
namespaceplane//名空間的定義
{
voidShowLength(intlen)//參數(shù)類型為int
{
cout<<"inplanenamespace:"<<len<<endl;
}
}
voidmain()
{
usingnamespacecar;
ShowLength(3);
ShowLength(3.8);
usingnamespaceplane;
ShowLength(93);
ShowLength(93.75);
getch();
}
運行結(jié)果:
incarnamespace:3
incarnamespace:3.8
inplanenamespace:93
incarnamespace:93.75
說明:
如果沒有名空間的干擾,函數(shù)重載時選擇規(guī)則將是非常簡單。只要實參是double類型,則調(diào)用的是前面的函數(shù);如果實參是int類型,則調(diào)用后面的函數(shù)。但是由于名空間的參與,就出現(xiàn)了上面的運行結(jié)果。所以在編程的時候一定要注意名空間對函數(shù)重載的影響。
應(yīng)注意:調(diào)用函數(shù)時,如果實參和形參的數(shù)據(jù)類型實在沒有辦法完全匹配,可能會對實參進行適當(dāng)?shù)臄?shù)據(jù)類型轉(zhuǎn)換。比如,將char類型轉(zhuǎn)換為int類型,或進一步將int類型轉(zhuǎn)換為double類型。這種是將數(shù)據(jù)類型從簡單往復(fù)雜轉(zhuǎn)換,一般不會丟失信息。另外一種轉(zhuǎn)換是反過來,將double類型轉(zhuǎn)換為int類型,或進一步將int類型轉(zhuǎn)換為char類型。這種是將數(shù)據(jù)類型從復(fù)雜往簡單轉(zhuǎn)換,可能會丟失部分信息。在調(diào)用函數(shù)的時候,不同的情況下,C++對上述兩種轉(zhuǎn)換的優(yōu)先級是不同的。當(dāng)引入了名空間后,則參與了上述優(yōu)先級順序的分配。
全局空間最大的問題在于它本身僅有一個。在大的軟件項目中,經(jīng)常會有不少人把他們定義的名字都放在這個單一的空間中,從而不可避免地導(dǎo)致名字沖突。例如,假設(shè)library1.h定義了一些常量,其中包括:
const double lib_version =1.204;
類似的,library2.h也定義了:
const int lib_version = 3;
如果某個程序想同時包含library1.h和library2.h就會有問題。作為程序員,盡力使自己的程序庫不給別人帶來這些問題。例如,可預(yù)先想一些不大可能造成沖突的某種前綴,加在每個全局符號前。當(dāng)然得承認,這樣組合起來的標(biāo)識符看起來不是那么令人舒服。
另一個比較好的方法是使用c++namespace。namespace本質(zhì)上和使用前綴的方法一樣,只不過避免了別人總是看到前綴而已。所以,不要這么做:
const double sdmbook_version=2.0;//在這個程序庫中, 每個符號以"sdm"開頭
//class sdmhandle { ... };
sdmhandle&sdmgethandle();//為什么函數(shù)要這樣聲明?
而要這么做:
namespace sdm {
constdouble book_version = 2.0;
classhandle { ... };
handle&gethandle();
}
用戶于是可以通過三種方法來訪問這一名字空間里的符號:將名字空間中的所有符號全部引入到某一用戶空間;將部分符號引入到某一用戶空間;或通過修飾符顯式地一次性使用某個符號:
void f1()
{
usingnamespacesdm;//使得sdm中的所有符號不用加修飾符就可以使用
cout<<book_version;//解釋為sdm::book_version
...
handle h=gethandle();//handle解釋為sdm::handle,
//gethandle解釋為sdm::gethandle
...
}
void f2()
{
usingsdm::book_version;//使得僅book_version不用加修飾符就可以使用
cout<<book_version;//解釋為sdm::book_version
...
handle h=gethandle();//錯誤! handle和gethandle
//都沒有引入到本空間
...
}
void f3()
{
cout<<sdm::book_version;//使得book_version在本語句有效
...
double d=book_version;//錯誤! book_version不在本空間
handle h=gethandle();//錯誤! handle和gethandle都沒有引入到本空間
...
}
有些名字空間沒有名字。這種沒命名的名字空間一般用于限制名字空間內(nèi)部元素的可見性。
名字空間帶來的最大的好處之一在于:潛在的二義不會造成錯誤。所以,從多個不同的名字空間引入同一個符號名不會造成沖突(假如確實真的從不使用這個符號的話)。例如,除了名字空間sdm外,假如還要用到下面這個名字空間:
namespace acmewindowsystem {
...
typedef inthandle;
...
}
只要不引用符號handle,使用sdm和acmewindowsystem時就不會有沖突。假如真的要引用,可以明確地指明是哪個名字空間的handle:
void f()
{
usingnamespacesdm;//引入sdm里的所有符號
usingnamespaceacmewindowsystem;//引入acme里的所有符號
...//自由地引用sdm和acme里除handle之外的其它符號
handleh;//錯誤! 哪個handle?
sdm::handleh1;//正確, 沒有二義
acmewindowsystem::handleh2;//也沒有二義
...
}
假如用常規(guī)的基于頭文件的方法來做,只是簡單地包含sdm.h和acme.h,這樣的話,由于handle有多個定義,編譯將不能通過。
名字空間的概念加入到c++標(biāo)準(zhǔn)的時間相對較晚,所以有些人會認為它不太重要,可有可無。但這種想法是錯誤的,因為c++標(biāo)準(zhǔn)庫里幾乎所有的東西都存在于名字空間std之中。它有一種直接的影響方式:c++提供了那些沒有擴展名的頭文件,如,等。
由于名字空間的概念引入的時間相對較晚,有些編譯器可能不支持。就算是這樣,那也沒理由污染全局名字空間,因為可以用struct來近似實現(xiàn)namespace??梢赃@樣做:先創(chuàng)建一個結(jié)構(gòu)用以保存全局符號名,然后將這些全局符號名作為靜態(tài)成員放入結(jié)構(gòu)中:
// 用于模擬名字空間的一個結(jié)構(gòu)的定義
struct sdm {
staticconst double book_version;
classhandle { ... };
statichandle&gethandle();
};
const double sdm::book_version=2.0;//靜態(tài)成員的定義
現(xiàn)在,如果有人想訪問這些全局符號名,只用簡單地在它們前面加上結(jié)構(gòu)名作為前綴:
void f()
{
cout<<sdm::book_version;
...
sdm::handleh = sdm::gethandle();
...
}
如果全局范圍內(nèi)實際上沒有名字沖突,用戶就會覺得加修飾符麻煩而多余。幸運的是,還是有辦法來讓用戶選擇使用它們或忽略它們。
對于類型名,可以用類型定義(typedef)來顯式地去掉空間引用。例如,假設(shè)結(jié)構(gòu)s(模擬的名字空間)內(nèi)有個類型名t,可以這樣用typedef來使得t成為s::t的同義詞:
typedef sdm::handle handle;
對于結(jié)構(gòu)中的每個(靜態(tài))對象x,可以提供一個(全局)引用x,并初始化為s::x:
const double& book_version =sdm::book_version;
處理函數(shù)的方法和處理對象一樣,但要注意,即使定義函數(shù)的引用是合法的,但代碼的維護者會更喜歡使用函數(shù)指針:
sdm::handle& (* constgethandle)()=//gethandle是指向sdm::gethandle
sdm::gethandle;//的const 指針
注意gethandle是一個常指針。因為當(dāng)然不想讓用戶將它指向別的什么東西,而不是sdm::gethandle。
如果真想知道怎么定義一個函數(shù)的引用,看看下面:
sdm::handle&(&gethandle)()=//gethandle是指向
sdm::gethandle;//sdm::gethandle的引用
除了初始化的方式外,函數(shù)的引用和函數(shù)的常指針在行為上完全相同,只是函數(shù)指針更易于理解。
有了上面的類型定義和引用,那些不會遭遇全局名字沖突的用戶就會使用沒有修飾符的類型和對象名;相反,那些有全局名字沖突的用戶就會忽略類型和引用的定義,代之以帶修飾符的符號名。還要注意的是,不是所有用戶都想使用這種簡寫名,所以要把類型定義和引用放在一個單獨的頭文件中,不要把它和(模擬namespace的)結(jié)構(gòu)的定義混在一起。
struct是namespace的很好的近似,但實際上還是相差很遠。它在很多方面很欠缺,其中很明顯的一點是對運算符的處理。如果運算符被定義為結(jié)構(gòu)的靜態(tài)成員,它就只能通過函數(shù)調(diào)用來使用,而不能象常規(guī)的運算符所設(shè)計的那樣,可以通過自然的語法來使用:
// 定義一個模擬名字空間的結(jié)構(gòu),結(jié)構(gòu)內(nèi)部包含widgets的類型
// 和函數(shù)。widgets對象支持operator+進行加法運算
struct widgets {
classwidget { ... };
staticconst widgetoperator+(const widget&lhs,constwidget& rhs);
...
};
// 為上面所述的widge和operator+ 建立全局(無修飾符的)名稱
typedef widgets::widget widget;
const widget (* constoperator+)(constwidget&,//錯誤!
constwidget&);//operator+不能是指針名
widget w1, w2, sum;
sum = w1+w2;//錯誤! 本空間沒有聲明
//參數(shù)為widgets 的operator+
sum =widgets::operator+(w1,w2);//合法, 但不是"自然"的語法
正因為這些限制,所以一旦編譯器支持,就要盡早使用真正的名字空間。
愛華網(wǎng)



