程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> VC >> 關於VC++ >> 在C++中實現屬性

在C++中實現屬性

編輯:關於VC++

開發測試環境:Visual C++ 7.0, Windows XP sp1, Windows 2000 sp3

摘要

本文試著在C++中不使用任何擴展技術模擬C#(或其他語言)中的屬性特征。大多數在C++實現屬性的庫和編譯器使用擴展技術,如Managed C++或C++ Builder,或者他們使用如通常函數的set和get方法,但那不是屬性。

詳述

我們首先看一下什麼是屬性。一個屬性表現為一個字段或者成員變量,但它通過read和write方法或者get和set方法暗中操作變量。

例如,若存在類A和它的屬性Count,我可以寫如下的代碼:

A foo;
Cout << foo.Count;
實際上Count調用它的get函數返回當前的變量值。你可以將屬性定為只讀(你可以讀取它但不能修改它)、只寫或者可讀寫,這就是使用屬性而不直接使用變量的的一個最大好處了。好了,讓我們開始來實現它:

我們需要能做如下的事:

int i = foo.Count; //--調用get函數得到值
foo.Count = i; //-- 調用set函數設定值
因此,很明顯的我們需要重載''=''操作符使其能設定變量的值,同時也要重載該屬性的返回值(在下面我們將會看到的)。

我們將實現一個稱為property的類,它做的就像一個屬性,聲明如下:

template <typename Container, typename ValueType, int nPropType>
class property {}
這個模板類表示的是我們的屬性。Container是我們要在其中包含屬性的類變量,set和get方法以及屬性的類的類型。ValueType是內部變量即要定義的屬性的類型,nPropType定義屬性的讀寫標志:只讀、只寫或可讀寫。現在我們需要一個指向從包含屬性的類Container到屬性類property的set和get方法的指針,同時重載''=''操作符以使得屬性能象變量起那樣作用。現在我們來看property類的全部定義

#define READ_ONLY 1
#define WRITE_ONLY 2
#define READ_WRITE 3
template <typename Container, typename ValueType, int nPropType>
class property
{
public:
property()
{
m_cObject = NULL;
Set = NULL;
Get = NULL;
}
//-- 將m_cObject指向包含屬性的container類 --
void setContainer(Container* cObject)
{
m_cObject = cObject;
}
//-- 設定可改變屬性值的set成員函數 --
void setter(void (Container::*pSet)(ValueType value))
{
if((nPropType == WRITE_ONLY) || (nPropType == READ_WRITE))
Set = pSet;
else
Set = NULL;
}
//-- 設定可檢索屬性值的get成員函數 --
void getter(ValueType (Container::*pGet)())
{
if((nPropType == READ_ONLY) || (nPropType == READ_WRITE))
Get = pGet;
else
Get = NULL;
}
//-- 重載''=''號操作符使其能用set成員設定屬性值--
ValueType operator =(const ValueType& value)
{
assert(m_cObject != NULL);
assert(Set != NULL);
(m_cObject->*Set)(value);
return value;
}
//-- 使屬性類能轉換為內部類型成為可能--
operator ValueType()
{
assert(m_cObject != NULL);
assert(Get != NULL);
return (m_cObject->*Get)();
}
private:
Container* m_cObject; //-- 指向包含屬性的類模塊 --
void (Container::*Set)(ValueType value);
//-- 指向set成員函數的函數指針 --
ValueType (Container::*Get)();
//-- 指向get成員函數的函數指針 --
};

現在讓我們來一段一段地看這些代碼:

在下面的代碼中,僅僅將Container指針指向一個有效的包含屬性的實例。

void setContainer(Container* cObject)
{
m_cObject = cObject;
}

下面的代碼,設定指針指向包含屬性的類中的set和get成員函數,其set和get成員函數度有,唯一的限制即set成員函數必須有一個ValueType型的參數並無返回值,get成員函數沒有參數,但要返回ValueType型值。

//-- 設定可改變屬性值的set成員函數 --
void setter(void (Container::*pSet)(ValueType value))
{
if((nPropType == WRITE_ONLY) || (nPropType == READ_WRITE))
Set = pSet;
else
Set = NULL;
}
//-- 設定可檢索屬性值的get成員函數 --
void getter(ValueType (Container::*pGet)())
{
if((nPropType == READ_ONLY) || (nPropType == READ_WRITE))
Get = pGet;
else
Get = NULL;
}
在如下的代碼中,第一部分是''=''操作符的重載,它調用包含屬性的類中的set函數設定其屬性的值。第二部分則為了使整個屬性類象ValueType類型一樣起作用,所以它返回包含屬性的類中get函數的返回值。//-- 重載''=''號操作符使其能用set成員設定屬性值--
ValueType operator =(const ValueType& value)
{
assert(m_cObject != NULL);
assert(Set != NULL);
(m_cObject->*Set)(value);
return value;
}
//-- 使屬性類能轉換為內部類型成為可能--
operator ValueType()
{
assert(m_cObject != NULL);
assert(Get != NULL);
return (m_cObject->*Get)();
}

現在我們來看看怎樣使用它:

如下所示,在PropTest類中定義了一個叫做Count的簡單屬性。Count的實際值將保存到或檢索之在PropTest的私有成員變量"m_nCount"中,通過PropTest的get和set方法。get和set方法可以使用任何的變量名字,只需他們的地址能被傳遞到property類中,如下面的PropTest構造函數裡面的代碼般,代碼行" property<PropTest, int, READ_WRITE> Count; "讓我們在PropTest中得到可讀寫的int型的Count屬性。現在你可以使用如一般的成員變量般使用使用Count屬性了,但實際上你是間接地調用它set和get方法。

要使Count屬性能成功工作,必須先在PropTest的構造函數裡面對其進行初始化。

class PropTest
{
public:
PropTest()
{
Count.setContainer(this);
Count.setter(&PropTest::setCount);
Count.getter(&PropTest::getCount);
}
int getCount()
{
return m_nCount;
}
void setCount(int nCount)
{
m_nCount = nCount;
}
property<PropTest,int,READ_WRITE> Count;
private:
int m_nCount;
};
如下所示,你可以象使用普通變量一樣使用Count屬性。int i = 5,j;
PropTest test;
test.Count = i;  //-- 調用set函數 --
j= test.Count;   //-- 調用get函數 --
要使用只讀的屬性,你可以創建如下的property實例:property<PropTest,int,READ_ONLY > Count;要使用只寫的屬性,你可以創建如下的property實例:property<PropTest,int,WRITE_ONLY > Count;注意:如果你將某一屬性設為只讀,當你對其賦值時,將引發assertion診斷。同理,當讀取只寫的屬性時

也同樣會引發assertion診斷。

小結

本文展示了在C++只用標准的C++特性而不使用其他任何的擴展技術來實現屬性。當然,直接使用set和get函數效率

要更高些,因為本文中的方法需要為每一個屬性定義一個property類實例。

本文配套源碼

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