2012-04-20 69 views
1

當談到創建類時,我被告知沒有公共數據成員。這很好,我明白爲什麼,但這是我的問題。我有一個我在類中使用的結構(線性鏈表)。我真的很想將其中一個struct字段(一個數組)初始化爲NULL,這樣我就可以檢查客戶端是否傳遞了有效的結構,而不是未經初始化的那些充滿垃圾值的結構。我意識到C++不會讓我在struct聲明中設置一個默認值,所以我如何保護客戶端不給我垃圾?結構或類,公共數據呢?

struct task { 
    char *description; 
    char *name; 
    float time_remaining; 
    float time_spent; 
}; 

然後在我的課,我試圖做一些事情,如:

//I am making a copy of "to_add" and storing it in the LLL 
int list::add_to_list(const task & to_add) 
{ /.../ } 

我不希望用戶添加一堆未初始化「任務的」到鏈表...什麼去做?當我將該結構轉換爲類並將數據成員移動到私有時,我嘗試訪問數據成員以製作它們的副本。我非常小心,不要做任何事情來影響var的值,但是我無法擺脫編譯器給我提供有關「錯誤:將'const task''作爲'char'task :: get_comp_name ()'丟棄限定符[-fpermissive]「(」get_comp_name「)是我確定沒有編輯任何值的獲取者之一,只是傳給我一個副本)請在拍攝自己之前幫助我。在臉上。

+0

我無法理解問題。沒有公共數據成員意味着訪問可能對「外部」世界「有趣」的數據的唯一方式是通過吸氣劑,如果需要設置它們,則必須通過一個setter來完成。當一個實例被創建時,你可以將你的私有成員初始化爲任何你想要的。任何從外部作爲方法參數傳遞的東西都可能是不安全的,但這是「正常的」,我不明白你是如何將它與非公開數據要求相耦合的,它們在我看來有兩個不同的「事實」。你能解釋得更好嗎? – ShinTakezou 2012-04-20 05:42:12

+0

錯誤是因爲你沒有聲明函數const。如果你真的想提供訪問者而不是公共數據,那麼getter應該像'char const * get_comp_name()const;'那樣。 – 2012-04-20 06:25:51

回答

4

在C++中,一個struct和一個class除了訪問控制外都是一樣的。所以結構對成員和繼承的默認訪問是公共的,而類'一個是私有的。所以你可以給你的struct一個defult構造函數和其他的來初始化它。

struct task { 
    task() : desctiption(0), name(0), time_remaining(0.), time_spent(0.) {} 
    char *description; 
    char *name; 
    float time_remaining; 
    float time_spent; 
}; 

添加構造函數的一個副作用是該結構不再是聚合。這對你來說可能是也可能不是問題。

在C++ 11,你還可以在聲明的時候初始化成員:

struct task { 
    char *description{nullptr}; 
    char *name{nullptr}; 
    float time_remaining{0}; 
    float time_spent{0}; 
}; 

這就地初始化接受type x = y語法也和爭論少{}初始化結果值初始化爲,這導致對初始類型的零初始化爲,因此可以省略示例中的參數。

+0

+1。順便說一下,'char * name {}'就足夠了。同樣,'float time_spent {}'。 [更多這裏](http://stackoverflow.com/questions/10147264/braces-around-string-literal-in-char-array-declaration-valid-e-g-char-s/10147335#10147335)。 – Nawaz 2012-04-20 05:44:36

+0

@Nawaz確實,我會添加一些東西。 – juanchopanza 2012-04-20 05:48:31

+0

就是這樣!該死的我愛你們。這麼多聰明的人在這裏。萬分感謝! – MCP 2012-04-20 05:50:27

1

的結構實現一個構造函數:

struct task { 
    task() : description(0), name(0), time_remaining(0), time_spent(0) {} 
    char *description; 
    char *name; 
    float time_remaining; 
    float time_spent; 
}; 

類和C++中的結構之間的唯一區別是它的成員的默認可訪問性。

+0

另一個區別是默認繼承,這是公共的結構和私人的類。 – juanchopanza 2012-04-20 05:47:13

+0

@Andreas:在C++中* visibility *和* accessibility *有區別。你應該寫的是,*可訪問性*,**不** *可見性*。 – Nawaz 2012-04-20 05:48:26

2

這裏有幾個問題。

公開還是不公開?

公共屬性看起來很方便,但通常會在最不經意的時候回來咬你。我已經懷疑time_remainingtime_spent有問題了:我想這兩個都是在相同時刻修改過的,不是嗎?

默認情況下,變量屬性應該是private,使類別可以執行不變量作爲這樣time_remaining + time_spent在整個任務的壽命的常數。

對於常量屬性,它可以是public,它們在不變量中的作用無論如何都是在構造函數中一次性完成的。

但奇怪的錯誤消息?

這是因爲你缺乏一個很好的教程或書籍。手頭的問題很簡單:這是一個與const相關的問題。

A const對象只能通過const引用或值傳遞給函數/方法,並且只能調用const方法。在你的情況下,name()方法的正確聲明在方法名稱後面應該有一個const限定符。

把它完全

而且在std::string扔,因爲它是如此容易操縱。

class Task { 
public: 
    Task(): time_remaining(0), time_spent(0) {} 
    Task(std::string name, std::string desc, float duration): 
     _name(name), _desc(desc), _time_remaining(duration), _time_spent(0) {} 

    // Accessors 
    std::string const& name() const { return _name; } 
    std::string const& description() const { return _desc; } 
    float time_remaining() const { return _time_remaining; } 
    float time_spent() const { return _time_spent; } 

    // Modifiers 
    void spend(float duration) { 
     _time_remaining -= duration; 
     _time_spent += duration; 
    } 

private: 
    std::string _name, _desc; 
    float _time_remaining, _time_spent; 
}; // class Task 

注:它可能是有益的檢查傳遞給spend方法duration並不優於_time_remaining屬性,否則你花更多的比你...

+0

這看起來像一個偉大的宣言!所以到了這一點。就訪問者而言:因爲你正在使用字符串,那些訪問器只是返回一個副本,對吧?如果你正在使用一個數組(如指針)呢?請問函數名後的「const」是否足以讓一個訪問/創建數組的獨立副本? – MCP 2012-04-20 15:20:18

+1

@MCP:不是,它們正在返回'std :: string const&',它是對字符串的const引用。如果調用者寫入'std :: string const&name = t.name();'她得到一個const引用,如果她寫入'std :: string const name = t.name();'(巧妙地缺少' ')她得到一個'const'值(而不是'const'在後一種情況下是可選的)。方法上的'const'意味着你不能改變類的內部屬性。如果這個類持有一個指針,那麼指針本身不能被改變,但是它指向的對象可能會被改變,如果它不是'const'限定的。 – 2012-04-20 15:47:09

+0

@MCP:你應該在這個網站或教程上尋找問題來理解'const'-ness。如果解釋得當,這是一個很簡單的話題,但如果不是這樣,它可能會變得非常混亂。特別是因爲它不僅僅是技術性的,而且還可以用於邏輯「常量」,通常更有用,這需要一些關於概念的經驗(以及開始的準則)。 – 2012-04-20 15:48:55