隱藏.cpp裡一切細節的範例程式

  1. 隱藏.cpp裡一切細節的範例程式
    1. 程式執行結果:
    2. 原本的程式
      1. 主程式
      2. //Person.h v1.0
      3. //Person.cpp v1.0
      4. //address.h v1.0
      5. //address.cpp v1.0
      6. //date.h v1.0
      7. //date.cpp v1.0
    3. 隱藏Person實作的成員變數
      1. //Person.h v1.0.1
      2. //Person.cpp v1.0.1
      3. //PersonImpl.cpp

隱藏.cpp裡一切細節的範例程式

原文連結: https://darkblack01.blogspot.com/2012/09/cpp.html
移植時的最後更新日期: 2015-12-23T14:16:57.668+08:00

在C中,分離類別實作和類別介面的做法有幾個優點:

  1. 編譯時可以減少因為修改而牽動的檔案數量,大幅降低檔案重新編譯的規模(Effective C 2nd #37, 3rd #31)
  2. 在提供別人編譯所需要的檔案時,可以成功讓人編譯,又不會導致自己的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和適當命名的副程式,就可以隱藏一切的基礎類別,而使用自己訂的字來當程式碼。