- 編譯時可以減少因為修改而牽動的檔案數量,大幅降低檔案重新編譯的規模(Effective C++ 2nd #37, 3rd #31)
- 在提供別人編譯所需要的檔案時,可以成功讓人編譯,又不會導致自己的Source Code被看光,而破壞類別的封裝性,或被修改程式碼,破壞了類別的整體概念性。
基於以上兩點優點,一定要學下這一招。
去翻了一下Effective C++ 2rd #37,以下是以它的程式碼為基礎,所做的練習。
程式執行結果:
阿童木生於2003/04/07,目前住在日本原本的程式
主程式
#include <iostream>
#include "Person.h"
#include "date.h"
#include "address.h"
using namespace std;
int main()
{
Address theAddr("日本");
Date theDate("2003/04/07");
Person thePersonOne("阿童木", theDate, theAddr);
cout << thePersonOne.name() << "生於" <<
thePersonOne.birthDate() << "目前住在" <<
thePersonOne.address() << endl;
return 0;
}
//Person.h v1.0
#include <string>
#include "date.h"
#include "address.h"
class Person
{
std::string theName;
Date theBirthDate;
Address theAddress;
public:
Person();
Person(const std::string& name,
const Date& birthday,
std::string name() const;
std::string birthDate() const;
std::string address() const;
//...
};
//Person.cpp v1.0
#include "Person.h"
Person::Person(){}
Person::Person(const std::string& name, const Date& birthday, const Address& addr)
{
theName = name;
theBirthDate = birthday;
theAddress = addr;
}
std::string Person::name() const{ return theName; }
std::string Person::birthDate() const{ return theBirthDate.date(); }
std::string Person::address() const{ return theAddress.addr(); }
//address.h v1.0
#include <string>
class Address
{
std::string theAddr;
public:
Address();
Address(const std::string& addr);
std::string addr() const;
void set(const std::string);
};
//address.cpp v1.0
#include "address.h"
Address::Address(){}
Address::Address(const std::string& addr){ theAddr = addr; }
std::string Address::addr() const
{
return theAddr;
}
//date.h v1.0
#include <string>
class Date
{
std::string theDate;
public:
Date();
Date(const std::string& date);
std::string date() const;
void Set(const std::string );
};
//date.cpp v1.0
#include "date.h"
Date::Date(){}
Date::Date(const std::string& date){ theDate = date; }
std::string Date::date() const
{
return theDate;
}
隱藏Person實作的成員變數
以下的做法,只要在專案內加入Person.o、PersonImpl.o取代相對應的.cpp檔。//Person.h v1.0.1
#include <string>
#include "date.h"
#include "address.h"
struct PersonImpl; //要要做一個類別,並且先在這宣告
//因為它的.h和.cpp檔不給,只給它的.obj檔,以隔壁實作(不用重新編繹了)
class Person
{
// std::string theName; //這三行註解是要被隱藏的地方
// Date theBirthDate; //原本的實作,之後要刪掉!
// Address theAddress; //在此顯示只是為了做對照
PersonImpl* pImpl; //宣告一個實作類別的指標(或參考也行,就是不可以是實體)
public:
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 v1.0.1
//之後的這個檔案也沒有要給#include "Person.h"
#include "PersonImpl.cpp" //在這include,就可以不用給PersonImpl.cpp
Person::Person(){}
Person::Person(const std::string& name, const Date& birthday, const Address& addr)
{
pImpl = new PersonImpl(); //要在這new一個PersonImpl的物件
pImpl->theName;
pImpl->theBirthDate;
pImpl->theAddress;
}
std::string Person::name() const{ return pImpl->theName; }
std::string Person::birthDate() const{ return pImpl->theBirthDate.date(); }
std::string Person::address() const{ return pImpl->theAddress.addr(); }
//PersonImpl.cpp
#include <string>
#include "date.h"
#include "address.h"
struct PersonImpl
{
std::string theName;
Date theBirthDate;
Address theAddress;
};
以上,再配合typedef和適當命名的副程式,就可以隱藏一切的基礎類別,而使用自己訂的字來當程式碼。
沒有留言:
張貼留言
(什麼是留言欄訊息?)