2012-02-05 63 views
2

我已經瞭解到,
type fields is an error-prone technique somewhere是什麼類型的字段

谷歌也很多,但我。雖然沒有令人滿意的結果知道typefields單獨的含義。我在想,類型字段意味着特定類型的字段,如

class marks; 
class test { 
marks number; 
bool pass; 
} 

這裏根據我的類型字段是數字和通過。 如果這是正確的如何是組成不同呢? 什麼是type field技術?它是如何容易出錯的?

請給出它的真正含義。還舉一個例子來表明它的邪惡本質和它的替代品是什麼?

+1

你好,無論我多麼努力地嘗試,我都無法理解你的意思以及你想問什麼。你能否嘗試以更明瞭的方式重寫問題? – Lefteris 2012-02-05 05:39:04

+1

這是一個有效的問題。如果您不明白OP要詢問什麼,請不要將其投票爲*不是真正的Q *或*非建設性的*,它不是它們中的任何一個。 – 2012-02-05 05:47:39

+0

@AIs我沒有downvote OP。只是要求澄清他的問題,因爲我不明白他指的是什麼。無論如何,Silico的回覆似乎是OP所要求的。 不知道他們把這種做法稱爲類型字段 – Lefteris 2012-02-05 05:51:51

回答

6

你幾乎肯定是指Bjarne Stroustrup在書The C++ Programming Language中討論的類型字段。這個上下文中的類型字段只是一個基類中的某種變量,它指示了它的子類的實際類型。這裏有一個例子:

class Pet 
{ 
public: 
    enum PetType { Dog, Cat, Bird, Fish }; 

    void ToString() 
    { 
     switch(type) 
     { 
     case Pet::Dog: std::cout << "Dog" << std::endl; break; 
     case Pet::Cat: std::cout << "Cat" << std::endl; break; 
     case Pet::Bird: std::cout << "Bird" << std::endl; break; 
     case Pet::Fish: std::cout << "Fish" << std::endl; break; 
     } 
    } 

private: 
    PetType type; // A type field. 
}; 

class Dog : public Pet 
{ 
public: 
    Dog() { type = Dog; } 
}; 

// And so on... 

void Test(const Pet& p) { p.ToString(); } 
int main() 
{ 
    Dog d; 
    Test(d); 
    return 0; 
} 

這是實現ToString()方法一個非常脆弱的方式。每次需要添加派生類Pet時,都需要更新PetType枚舉和ToString()方法。例如,如果我需要一個Turtle子類,我需要做這些改變:

// ... 
enum PetType { Dog, Cat, Bird, Fish, Tutle /* Added */}; 
void ToString(const Pet& p) 
{ 
    switch(p.type) 
    { 
    case Pet::Dog: std::cout << "Dog" << std::endl; break; 
    case Pet::Cat: std::cout << "Cat" << std::endl; break; 
    case Pet::Bird: std::cout << "Bird" << std::endl; break; 
    case Pet::Fish: std::cout << "Fish" << std::endl; break; 
    case Pet::Turtle: std::cout << "Turtle" << std::endl; break; // Added 
    } 
} 
// ... 
class Turtle : public Pet 
{ 
public: 
    Turtle() { type = Turtle; } // Added 
}; 

試想一下,如果Pet類有不僅僅是ToString()更多的功能;維護成爲一場噩夢。這是很多需要更改的代碼,但重要的是,爲了有一個Turtle類,我需要修改Pet類。這意味着需要更多的測試,代碼審查等。這明顯違反了the open/closed principle。這就是爲什麼類型字段非常容易出錯的原因。

一個顯著優越的方法是使用virtual功能:上面的代碼不需要額外enum S或switch聲明

class Pet 
{ 
public: 
    virtual void ToString() = 0; 
}; 

class Dog : public Pet 
{ 
public: 
    virtual void ToString() { std::cout << "Dog" << std::endl; } 
}; 

class Turtle : public Pet 
{ 
public: 
    virtual void ToString() { std::cout << "Turtle" << std::endl; } 
}; 

// And so on... 

void Test(const Pet& p) { p.ToString(); } 
int main() 
{ 
    Turtle t 
    // Will call Turtle::ToString(), even though 
    // Test() was only given a const Pet& 
    Test(t); 
    return 0; 
} 

注意。調用Pet::ToString()將自動調用ToString()Dog s,Cat s等的正確實現,代碼少得多。我甚至不需要更改Pet課程;假如已經定義了Pet,我可以根據需要放入Turtle類。


對於可能合法使用類型字段see this Stack Overflow question and the answers to that question

+1

+1。我實際上即將添加一個答案,但隨後將其刪除,因爲您的答案看起來很有希望。儘管如此,爲了完整起見,您可以解釋爲什麼第一種方法*脆弱*,它如何違反導致設計不良的* SOLID *設計原則。 – 2012-02-05 05:45:29

+0

Dog(){type = Dog; }私人會員如何訪問!!!!!!!!! – 2015-02-05 12:19:01