日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C++11:using 的各种作用

發布時間:2023/12/31 c/c++ 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++11:using 的各种作用 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

C++11中using關鍵字的主要作用是:為一個模板庫定義一個別名。

文章鏈接:派生類中使用using別名改變基類成員的訪問權限?

一、《Effective Modern C++》里有比較完整的解釋

各個作用

/*定義別名*/template<class T>using Tlist = std::list<T>;using Tlist = std::list<char>;Tlist listChar;//typedef void (*df)()using df = void(*)();/*使用外部構造*/using A::A;/*引用外部類型*/ using typename A;

二、Using 關鍵字的作用:重載父類函數

1.在當前文件中引入命名空間

???? 這是我們最熟悉的用法,例如:using namespace std;

2.在子類中使用?using?聲明引入基類成員名稱(參見C++ primer)

private或者protected繼承時,基類成員的訪問級別在派生類中更受限:

class Base { public: std::size_t size() const { return n; } protected: std::size_t n; }; class Derived : private Base { . . . };

在這一繼承層次中,成員函數?size?在?Base?中為?public,但在?Derived?中為?private。為了使?size?在?Derived?中成為?public,可以在?Derived?的?public
部分增加一個?using?聲明。如下這樣改變?Derived?的定義,可以使?size?成員能夠被用戶訪問,并使?n?能夠被?Derived的派生類訪問:

class Derived : private Base { public: using Base::size; protected: using Base::n; // ... };

另外,當子類中的成員函數和基類同名時,子類中重定義的成員函數將隱藏基類中的版本,即使函數原型不同也是如此(隱藏條件見下面)。

如果基類中成員函數有多個重載版本,派生類可以重定義所繼承的?0?個或多個版本,但是通過派生類型只能訪問派生類中重定義的那些版本,所以如果派生類想通過自身類型使用所有的重載版本,則派生類必須要么重定義所有重載版本要么一個也不重定義。有時類需要僅僅重定義一個重載集中某些版本的行為,并且想要繼承其他版本的含義,在這種情況下,為了重定義需要特化的某個版本而不得不重定義每一個基類版本,可能會令人厭煩??梢栽谂缮愔袨橹剌d成員名稱提供 using 聲明(為基類成員函數名稱而作的 using 聲明將該函數的所有重載實例加到派生類的作用域),使派生類不用重定義所繼承的每一個基類版本。一個 using 聲明只能指定一個名字,不能指定形參表,使用using聲明將名字加入作用域之后,派生類只需要重定義本類型確實必須定義的那些函數,對其他版本可以使用繼承的定義。

“隱藏”是指派生類的函數屏蔽了與其同名的基類函數,規則如下:

1、如果派生類的函數與基類的函數同名,但是參數不同。此時,不論有無virtual關鍵字,基類的函數將被隱藏(注意別與重載混淆)

2、如果派生類的函數與基類的函數同名,并且參數也相同,但是基類函數沒有virtual關鍵字。此時,基類的函數被隱藏(注意別與覆蓋混淆)

#include "StdAfx.h" #include <iostream> using namespace std; class Base { public: void menfcn(){cout<<"Base function"<<endl; }void menfcn(int n){cout<< cout<<"Base function with int"<<endl; } };class Derived : Base { public: using Base::menfcn;//using聲明只能指定一個名字,不能帶形參表 int menfcn(int) { cout<< cout<<"Derived function with int"<<endl; } }; int main() { Base b; Derived d; b.menfcn(); d.menfcn();//如果去掉Derived類中的using聲明,會出現錯誤:error C2660: 'Derived::menfcn' : function does not take 0 arguments std::cin.ignore(std::cin.gcount()+1);//清空緩沖區 std::cin.get();//暫停程序執行 }

三、需要注意的情況

子類中using引入基類函數時需要注意的情況
class base{ public:void test(){cout << "base::test()" << endl;}void test(int){cout << "base::test(int)" << endl;} }; class derived : public base{ public:void test(){cout << "derived::test()" << endl;} };
此時derived::test()會隱藏(hide)父類中的兩個test重載函數(base::test()和base::test(int)),因此我們為子類中加上一個using聲明:
class derived : public base{ public:void test(){cout << "derived::test()" << endl;}using base::test;//此聲明放在test前面和后面效果都一樣 };
現在會不會出現下面所述的情況呢?
---------------------------------------------------------------------------------------------------------------
既然using base::test將父類中的兩個test函數都引入子類,則子類中就相當于有了一個void test()函數,所以我們在子類中重新定義的void test()函數將會和從父類中引入的void test()函數發生沖突,進而出現“重定義”錯誤。
---------------------------------------------------------------------------------------------------------------
答案是:不會!
此時,子類中重新定義的void test()函數將“頂替”從父類中引入的void test()函數。
(PS:從父類中引入的另外一個void test(int)函數則沒有發生變化(仍然是父類中的函數實現)。) 類似的另外一種情況如下,此時加入了virtual:
class base{ public:virtual void test(){cout << "base::test()" << endl;}virtual void test(double){cout << "base::test(double)" << endl;}void test(int){cout << "base::test(int)" << endl;} }; class derived : public base{ public:void test(){cout << "derived::test()" << endl;} };
此時derived::test()雖然重寫(override)了base::test(),但是同時也隱藏(hide)父類中的兩個test重載函數(一個virtual函數base::test(double)和一個nonvirtual函數base::test(int))?,F在,我們為子類中加上一個using聲明:
class derived : public base{ public:void test(){cout << "derived::test()" << endl;}using base::test;//此聲明放在test前面和后面效果都一樣 };
與上面的類似,此時derived::test()“仍然重寫”了父類的base::test(),并且與父類中的base::test(double)和base::test(int)[在子類的域]中形成重載集合。
最后,留一個思考題目,如下:
class base{ public:virtual void test(){cout << "base::test()" << endl;}virtual void test(double){cout << "base::test(double)" << endl;}void test(int){cout << "base::test(int)" << endl;} }; class derived : public base{ public:void test(){cout << "derived::test()" << endl;}//using base::test; }; class A : public derived{ public:void test(double){cout << "A::test(double)" << endl;} }; int main(int argc, char **argv){base *pb = new A;pb->test(2.4);return 0; }
問題:derived中的using base::test加上與否,對程序的結果有什么影響?
答:沒有影響。(關鍵點:名字解析是編譯時期的事情,而virtual函數動態綁定是運行時期的事情。)
(PS:但是將main函數改成“derived *pd = new A; pd->test(2.4);”,則有區別了:如果將using base::test去掉,則編譯失敗。)

總結

以上是生活随笔為你收集整理的C++11:using 的各种作用的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。