題目
代碼
#include <cstring> // 包含字符串處理函數庫,如strlen、strncpy等
#include <iostream> // 包含輸入輸出流庫,用于cout等操作
using namespace std; // 使用標準命名空間,避免重復書寫std::class mystring { // 定義mystring類,用于字符串處理
private: // 私有成員,僅類內部可訪問char* str; // 指向動態分配的字符數組,存儲字符串內容size_t len; // 存儲字符串占用的空間大小(包括結束符'\0')public: // 公有成員,類外部可訪問// 默認構造函數,創建長度為10的空字符串mystring() : len(10) { // 初始化列表,將len初始化為10str = new char[len]; // 動態分配長度為len的字符數組// 初始化為空字符串str[0] = '\0'; // 將第一個字符設為結束符,代表空字符串}// 打印字符串內容(const成員函數,不修改對象狀態)void print() const {cout << str << endl; // 輸出字符串內容并換行}// 獲取空間大小(const成員函數,不修改對象狀態)size_t getSize() const {return len; // 返回字符串占用的空間大小}// 修改字符串內容,確保不越界void setContent(const char* newStr) { // 參數為常量字符串指針,避免修改源字符串// 取新字符串長度和現有空間較小值(減1是預留結束符位置),防止越界size_t newLen = min(strlen(newStr), len - 1); // strlen獲取新字符串實際長度strncpy(str, newStr, newLen); // 安全復制字符串,最多復制newLen個字符// 確保以'\0'結尾,避免輸出亂碼str[newLen] = '\0'; // 在復制的字符末尾添加結束符}// 析構函數,釋放動態分配的內存,防止內存泄漏~mystring() {delete[] str; // 釋放動態分配的字符數組}
};// 測試mystring類的功能
int main() {mystring s; // 創建mystring類的對象s,調用默認構造函數cout << "空間大小: " << s.getSize() << endl; // 輸出對象s的空間大小s.setContent("Hello"); // 調用setContent方法,設置字符串為"Hello"cout << "字符串內容: "; // 輸出提示信息s.print(); // 調用print方法,輸出字符串內容s.setContent("World! Long Text"); // 設置較長的字符串(會被截斷以適應空間)cout << "修改后內容: "; // 輸出提示信息s.print(); // 輸出修改后的字符串內容return 0; // 程序正常結束
}
關鍵點說明:
- 構造函數:
mystring()
?中動態分配內存,默認創建長度為 10 的字符數組,并初始化為空字符串。 setContent
:用?strncpy
?保證不會越界,最后手動加?'\0'
?確保字符串正確結束。- 析構函數:用?
delete[]
?釋放動態分配的內存,避免內存泄漏。 const
?成員函數:print
?和?getSize
?不會修改對象狀態,標記為?const
?更安全。
從代碼設計角度來看,是否使用?protected
(保護成員),取決于類的?繼承需求?和?設計意圖?。以下從幾個維度解釋當前代碼沒用到?protected
?的原因,以及何時適合用?protected
?:
1. 類的定位:無需繼承擴展
當前?mystring
?類是一個?獨立功能類?,設計目標是封裝字符串的基礎操作(構造、打印、修改內容等),沒有考慮讓其他類繼承它?。
protected
?的核心作用是?給子類開放訪問權限?(子類可訪問父類的?protected
?成員,外部類 / 函數不行 )。- 如果類不需要被繼承擴展,所有成員用?
private
(隱藏實現細節) +?public
(開放對外接口) 即可,protected
?就用不上。
2. 設計原則:隱藏實現細節
代碼里?str
?和?len
?是?private
?,這是?封裝思想?的體現:
private
?強制外部代碼通過?public
?接口(如?print
、getSize
、setContent
?)操作類,避免直接篡改內部狀態(比如直接修改?str
?指針導致內存混亂 )。- 如果把?
str
?或?len
?設為?protected
?,子類繼承后能直接訪問 / 修改它們,可能破壞父類的封裝邏輯(比如子類不小心改壞?str
?指針,父類功能就會異常 )。
3. 何時需要?protected
??
如果有?繼承擴展場景?,比如:
// 假設要繼承 mystring 擴展功能
class myAdvancedString : public mystring {
public:void doSomething() {// 子類想直接訪問父類的 len(假設 len 是 protected)// 如果父類 len 是 private,這里會編譯報錯;是 protected 則可以訪問size_t parentLen = len; // ... 基于父類狀態擴展邏輯}
};
這種情況下,若希望?子類能訪問父類的部分內部成員?(但又不想完全開放給外部 ),就可以把這些成員設為?protected
?。
總結
當前?mystring
?類因為?不需要被繼承?,所以用?private
?隱藏實現、public
?開放接口就足夠,無需?protected
?。如果未來有繼承擴展需求,再根據實際場景(需要子類訪問哪些內部成員 )決定是否引入?protected
?。