對C++中訪問private變數的思考
阿新 • • 發佈:2019-02-18
問題:如果自己動手寫CString類的建構函式,拷貝建構函式,解構函式,賦值運算子等,那麼該如何寫?
參考程式碼如下
#include <memory>
class MyString {
private:
char *m_data;
public:
MyString();
MyString(const char* ptr);
MyString(const MyString& rhs);
~MyString();
MyString& operator=(const MyString& rhs);
};
//預設的建構函式
MyString::MyString():m_data(new char[1]) {
m_data[0]='\0';
}
//使用const char* 來初始化
MyString::MyString(const char* ptr) {
if (NULL == ptr) {
m_data = new char[1];
*m_data = '\0';
} else {
int len = strlen(ptr);
m_data = new char[len + 1];
strcpy(m_data, ptr);
}
}
//拷貝建構函式
MyString::MyString(const MyString& rhs) {
int len = strlen(rhs.m_data);//注意,訪問了私有成員變數
m_data = new char[len + 1];
strcpy(m_data, rhs.m_data);//依舊訪問了私有成員變數
}
//賦值操作符
MyString& MyString::operator =(const MyString& rhs) {
if (this != &rhs) {
delete[] m_data;
m_data = new char[strlen(rhs.m_data)+1];//依舊訪問了私有成員變數
strcpy(m_data, rhs.m_data);//依舊訪問了私有成員變數
}
return *this;
}
編譯程式,未出現錯誤。但是從上述的程式碼中可以看出,我們訪問了rhs的私有成員變數m_data。從private的定義來看,我們是不能通過rhs訪問私有變數的,但是上述程式碼並未出現錯誤,這是為什麼?
對於類中的成員函式呼叫問題,我們知道,在編譯器將引數壓棧之前,會首先將this指標壓棧,且訪問成員變數也是通過this指標來訪問的,也就是說如下程式碼
void MyString::copy(const MyString &rhs)
{
m_data= rhs.m_data;
}
相當於
void MyString::copy(MyString *this ,const MyString &rhs)
{
this->m_data= rhs.m_data;
}
即this指標可以訪問私有成員m_data,那麼相應的rhs也可以訪問其私有成員m_data:編譯器按照相同的方式處理對私有成員的訪問。
在《C++PL》10.2.2 訪問控制 這一節寫到
1. “私有部分(private)只能由成員函式使用; 公用部分(public)則構成了該類的物件的公用介面.”
2. “對私有成員的保護依靠的是對於使用類成員名稱的限制. 可以通過地址操作和顯示的型別轉換等繞過這些限制. C++ 的保護只是為了避免無意的失誤, 而不是為了防止精心策劃的計謀(騙局).”
周星星(http://blog.vckbase.com/bruceteen)中:訪問許可權是應該對class控制還是應該對object控制,在各個語言裡不盡相同,但C++選擇了class。可能周星星的話更好的詮釋了為什麼可以訪問rhs的私有成員m_data.