程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 模板與繼承之藝術——空基類優化,模板繼承藝術優化

模板與繼承之藝術——空基類優化,模板繼承藝術優化

編輯:C++入門知識

模板與繼承之藝術——空基類優化,模板繼承藝術優化


1、概念 C++中有“空”類的概念,這就意味著在運行期間其內部不好任何內存。 只包含類型的成員函數、非虛成員函數和靜態數據成員的類為空類。 非靜態的數據成員,虛函數和虛基類則在運行時期消耗存儲空間。 2、空基類優化如下: #include<iostream> using namespace std; class Empty{      typedef int Int; };   class EmptyToo : public Empty {}; class EmptyThree : public EmptyToo {}; int main() {     cout << "sizeof(Empty):" << sizeof(Empty) << endl;     cout << "sizeof(EmptyToo):" << sizeof(EmptyToo)<< endl;     cout << "sizeof(EmptyThree):" << sizeof(EmptyThree) << endl; } (1)在類EmptyToo中類Empty沒有分配存儲空間 (2)帶有優化空基類的空類作為被繼承的基類(沒有其他基類時,單繼承)時,其大小也為0,這也就是EmptyTree 能和Empty具有相同大小的原因所在。   3、如果有其他基類時: #include<iostream> class Empty{     typedef int Int; };   class EmptyToo : public Empty{};   class EmptyThree : public Empty, public EmptyToo{}; int main() {     cout << "sizeof(Empty):"<< sizeof(Empty) << endl; //輸出1     cout << "sizeof(EmptyToo)" << sizeof(EmptyToo)<< endl; //輸出1     cout << "sizeof(EmptyThree):" << sizeof(EmptyThree) << endl; //輸出2 }   如果繼承時是多重繼承: EmptyThree中有兩個不同的子類Empty對象,一個是直接繼承來的Empty對象,另一個是EmptyToo繼承來的Empty對象。 由於是兩個對象所以不能讓其有相同的地址空間。即這裡優化(2)不起作用,EmptyThree是兩個Empty和EmptyToo大小之和。   4、將成員作為基類 只舉一例,模板參數確定會被實例化為類型(不是非類型,不是原生類型比如int),該模板類的另一個成員類型不是空類。如下: template<typename CustomClass> class Optimizable{     private:       CustomClass info;       void* storage; };   改寫為: template <typename CustomClass> class Optimizable {     private:        BaseMemberPair<CustomClass, void*> info_and_storage; };   // template<typename Base, typename Member> class BaseMemberPair : private Base{     private:          Member member; public:          BaseMemberPair(Base const &b, Member const &m):Base(b), member(m){} //通過first來訪問基類數據 Base const&  first() const{ return (Base const&)*this; } Base& first() const { return (Base&)*this; }   //通過second()來訪問成員變量 Member const& second() const { return this->member; } Member& second() const { return this->member; } };   優化前: #include<iostream> using namespace std; template<typename CustomClass> class Optimizable{ private: CustomClass info; void* storage; }; class Test{ }; int main() { cout << sizeof(Optimizable<Test>) << endl; //結果為8 return 0; } View Code

優化後:

#include<iostream> using namespace std; template<typename Base, typename Member> class BaseMemberPair : private Base{ private: Member member; public: BaseMemberPair(Base const &b, Member const &m):Base(b), member(m){} //通過first來訪問基類數據 Base const& first() const{ return (Base const&)*this; } //提供給const對象調用 Base& first() { return (Base&)*this; } //通過second()來訪問成員變量 Member const& second() const { return this->member; } Member& second() { return this->member; } }; template <typename CustomClass> class Optimizable { private: BaseMemberPair<CustomClass, void*> info_and_storage; }; class Test{ }; int main() { cout << sizeof(Optimizable<Test>) << endl; //結果為4 return 0; } View Code

5、警告:

針對下面的情況: template<typename T1, typename T2> class MyClass{       private:       T1 a;       T2 b; }; //優化 template<typename T1, typename T2> class MyClass : private T1, private T2{};   在不知道T1和T2是否為類型的情況下,最好不要盲目使用上面的優化方法,因為: (1)此方法不適用於原生類型int等 (2)如果T1, 和T2的類型相同繼承會出問題。 (3)增加基類會改變接口,因為多重繼承,如果T1和T2都有共同的基類Base的話,那麼MyClass中的數據成員,成員函數將會有二義性。所以此方法最好適應是之前提演示出的情況。   編輯整理:Claruarius,轉載請注明出處。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved