C++中的using 的作用,typedef與#define的區別


我們用到的庫函數基本上都屬於命名空間std的,在程序使用的過程中要顯示的將這一點標示出來,如std::cout。這個方法比較煩瑣,而我們都知道使用using聲明則更方便更安全。

2、命令空間的using聲明

我們在書寫模塊功能時,為了防止命名沖突會對模塊取命名空間,這樣子在使用時就需要指定是哪個命名空間,使用using聲明,則后面使用就無須前綴了。例如:

using std::cin;	//using聲明,當我們使用cin時,從命名空間std中獲取它
int main()
{
	int i;
	cin >> i;	//正確:cin和std::cin含義相同
	cout << i;	//錯誤:沒有對應的using聲明,必須使用完整的名字
	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

需要注意的是每個名字需要獨立的using聲明。例如:

using std::cin;	//必須每一個都有獨立的using聲明
using std::cout;  using std::endl;	//寫在同一行也需要獨立聲明
  • 1
  • 2

位於頭文件的代碼一般來說不應該使用using聲明。因為頭文件的內容會拷貝到所有引用它的文件中去,如果頭文件里有某個using聲明,那么每個使用了該頭文件的文件就都會有這個聲明,有可能產生名字沖突。

3、在子類中引用基類成員

在子類中對基類成員進行聲明,可恢復基類的防控級別。有三點規則:

  1. 在基類中的private成員,不能在派生類中任何地方用using聲明。
  2. 在基類中的protected成員,可以在派生類中任何地方用using聲明。當在public下聲明時,在類定義體外部,可以用派生類對象訪問該成員,但不能用基類對象訪問該成員;當在protected下聲明時,該成員可以被繼續派生下去;當在private下聲明時,對派生類定義體外部來說,該成員是派生類的私有成員。
  3. 在基類中的public成員,可以在派生類中任何地方用using聲明。具體聲明后的效果同基類中的protected成員。

例如:

class Base 
{
protected:
    void test1() { cout << "test1" << endl; }
    void test1(int a) {cout << "test2" << endl; }

    int value = 55;
};
 
class Derived : Base 	//使用默認繼承
{
public:
    //using Base::test1;	//using只是聲明,不參與形參的指定
    //using Base::value;
    void test2() { cout << "value is " << value << endl; }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

我們知道class的默認繼承是private,這樣子類中是無法訪問基類成員的,即test2會編譯出錯。但是如果我們把上面注釋的聲明給放開,則沒有問題。

注意:using::test1只是聲明,不需要形參指定,所以test1的兩個重載版本在子類中都可使用

4、使用using起別名

相當於傳統的typedef起別名。

typedef 	std::vector<int> intvec;
using 	intvec	= std::vector<int>;	//這兩個寫法是等價的
  • 1
  • 2

這個還不是很明顯的優勢,在來看一個列子:

typedef void (*FP) (int, const std::string&);
  • 1

若不是特別熟悉函數指針與typedef,第一眼還是很難指出FP其實是一個別名,代表着的是一個函數指針,而指向的這個函數返回類型是void,接受參數是int, const std::string&。

using FP = void (*) (int, const std::string&);
  • 1

這樣就很明顯了,一看FP就是一個別名。using的寫法把別名的名字強制分離到了左邊,而把別名指向的放在了右邊,比較清晰,可讀性比較好。比如:

typedef std::string (Foo::* fooMemFnPtr) (const std::string&);
    
using fooMemFnPtr = std::string (Foo::*) (const std::string&);
  • 1
  • 2
  • 3

來看一下模板別名

template <typename T>
using Vec = MyVector<T, MyAlloc<T>>;
 
// usage
Vec<int> vec;
  • 1
  • 2
  • 3
  • 4
  • 5

若使用typedef

template <typename T>
typedef MyVector<T, MyAlloc<T>> Vec;
 
// usage
Vec<int> vec;
  • 1
  • 2
  • 3
  • 4
  • 5

當進行編譯的時候,編譯器會給出error: a typedef cannot be a template的錯誤信息。

那么,如果我們想要用typedef做到這一點,需要進行包裝一層,如:

template <typename T>
struct Vec
{
  typedef MyVector<T, MyAlloc<T>> type;
};

// usage
Vec<int>::type vec;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

正如你所看到的,這樣是非常不漂亮的。而更糟糕的是,如果你想要把這樣的類型用在模板類或者進行參數傳遞的時候,你需要使用typename強制指定這樣的成員為類型,而不是說這樣的::type是一個靜態成員亦或者其它情況可以滿足這樣的語法,如:

template <typename T>
class Widget
{
  typename Vec<T>::type vec;
};
  • 1
  • 2
  • 3
  • 4
  • 5

然而,如果是使用using語法的模板別名,你則完全避免了因為::type引起的問題,也就完全不需要typename來指定了。

template <typename T>
class Widget
{
  Vec<T> vec;
};
  • 1
  • 2
  • 3
  • 4
  • 5

一切都會非常的自然,所以於此,模板起別名時推薦using,而非typedef。

所謂namespace,是指標識符的各種可見范圍。C++標准程序庫中的所有標識符都被定義於一個名為std的namespace中。

     iostream和iostream.h的區別:

     后綴為.h的頭文件C++標注已經明確提出不支持了。早些的實現將標准庫功能定義在全局空間里,聲明在帶.h后綴的頭文件里,C++標准為了和C區別開,也為了正確地使用命名空間,規定頭文件不使用后綴.h。因此,當使用<iostream.h>時,相當於在C中調用庫函數,使用的是全局命名空間,也就是早期的C++實現。當使用<iostream>時,該頭文件沒有定義全局命名空間,必須使用namespace std,這樣才能使用類似於cout這樣的C++標識符。

namespace是指標識符的各種可見范圍。
C++標准程序庫中的所有標識符都被定義於一個名為std的namespace中。 由於namespace的概念,使用C++標准程序庫的任何標識符時,可以有三種選擇:
直接指定標識符
例如std::iostream而不是iostream。完整語句如下: std::cout << std::hex << 3.4 << std::endl;
使用using關鍵字
using std::cout; using std::endl; using std::cin; 以上程序可以寫成如下代碼:
using std::cout <<using std::hex << 3.4 <<using std:: endl;
使用using namespace std
例如:
#include<iostream>
#include<sstream>
#include<string>
using namespace std;
這樣命名空間std內定義的所有標識符都有效(曝光)。就好像它們被聲明為全局變量一樣。那么以上語句可以如下寫: cout << hex << 3.4 << endl; 因為標准庫非常的龐大,所以程序員在選擇的類的名稱或函數名時就很有可能和標准庫中的某個名字相同。所以為了避免這種情況所造成的名字沖突,就把標准庫中的一切都放在名字空間std中。但這有會帶來了一個新問題。無數原有的C++代碼都依賴於使用了多年的偽標准庫中的功能,他們都是在全局空間下的,所以就有了<iostream>和<iostream.h>等等這樣的頭文件,一個是為了兼容以前的C++代碼,一個是為了支持新的標准。命名空間std封裝的是標准程序庫的名稱,標准程序庫為了和以前的頭文件區別,一般都不加".h"。

 

 

C++中的using namespace std的作用


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM