在此是要介紹,在C++中,如何實現「資訊隱藏狂熱」,class裡完全的將public以外的東西隱藏掉,在API設計中,這是很重要的,避免錯誤的使用,也讓設計更簡單好記。
在此,作者也有提到Effective C++ #34也有提及這個技巧。
無獨有偶的,Code Complete 2/e中也有提到。不過在《API Design for C++》中有強調,這是C++獨有的技巧,所以不算是通用的Design Pattern,不過,算是很厲害的Design Pattern for C++。
(在此,不使用書中的範例程式)
這個例子,是隱藏.cpp裡一切細節的範例程式的延伸版。
類別要描述的是「不會透露自己的年紀的人」。
透過pimpl技巧,強調「不會透露自己的年紀的人,更不會跟別人透露不想提及的意圖」。
//Person.h
#include <string>
#include "date.h"
#include "address.h"
class Person
{
std::string theName;
Date theBirthDate;
Address theAddress;
int GetYears(int currYear);
public:
Person();
~Person();
Person(const std::string& name,
const Date& birthday,
std::string name() const;
std::string birthDate() const;
std::string address() const;
//...
};
極致的資訊隱藏手法
我們希望它可以只露出必要的部份,所以將它改寫成這樣//Person.h
#include <string>
#include "date.h"
#include "address.h"
class Person
{
class PersonImpl; //如果使用上造成太多存取的限制,可以考慮將這一行改成public
PersonImpl* pImpl; //宣告一個實作類別的指標(或參考也行,就是不可以是實體)
public:
Person();
~Person();
Person(const std::string& name,
const Date& birthday,
const Address& addr);
std::string name() const;
std::string birthDate() const;
std::string address() const;
//...
};
//Person.cpp
#include "Person.h"
class Person::PersonImpl
{
public:
std::string theName;
Date theBirthDate;
Address theAddress;
int GetYears(int currYear)
{
return currYear - BirthDate.Year();
}
};
Person::Person(const std::string& name,
const Date& birthday,
const Address& addr):
pImpl(new PersonImpl())
{
pImpl->theName = name;
pImpl->theBirthDate = birthday;
pImpl->theAddress = addr;
};
Person::~Person()
{
delete pImpl;
pImpl = 0;
}
除此之外,對於類別的複製建構式與賦值運算子的override都是必須要注意的實作細節唷。使用Smart Pointer
書裡還建議使用smart pointer避免使用這種方式時,pimpl實作不見了的情況。//Person.h
#include <personimpl>
#include "date.h"
#include "address.h"
class Person
{
class PersonImpl; //如果使用上造成太多存取的限制,可以考慮將這一行改成public
std::unique_ptr pImpl; //使用適合的Smart Pointer
public:
Person();
~Person();
explicit Person(const std::string& name,
const Date& birthday,
const Address& addr);
std::string name() const;
std::string birthDate() const;
std::string address() const;
//...
};
- shared_ptr 指向相同的物件,誤刪不消失。
- scoped_ptr 保證唯一,無法複製。
pImpl的優點
- Information Hidding
- 降低耦合
- 加快編譯
- ...
pImpl的缺點
- 增加一點點的物件大小
- 降低程式碼可讀性
- 提高維護程本(除錯時要追程式碼就困難許多了)
- 類別中的const函數,無法保證private的成員變數唯讀(只保證pImpl的指標不改變)
而這篇就是紀錄書中,如何改寫的注意事項。
詳細的細節,還是去看書吧!^^這本書很棒唷!
沒有留言:
張貼留言
(什麼是留言欄訊息?)