2012-07-20 67 views
3

在虛擬構造函數習慣用法中有虛擬函數返回使用虛擬函數的新對象或對象的副本。但是,然後以多態的方式調用這些虛函數,必須使用實際構造函數創建該類的對象。虛擬構造函數成語和工廠設計

在設計模式上下文中,這意味着客戶端在使用多態對象創建方式之前知道對象的類型?

回答

5

客戶端不一定要知道具體的類型。例如,考慮這個層次結構:

struct Base 
{ 
    virtual ~Base(); 
    virtual Base * clone() const = 0; 
    static Base * create(std::string const &); 
    // ... 
}; 

struct A : Base { A * clone() const { return new A(*this); } /* ... */ }; 
struct B : Base { B * clone() const { return new B(*this); } /* ... */ }; 
struct C : Base { C * clone() const { return new C(*this); } /* ... */ }; 

Base * Base::create(std::string const & id) 
{ 
    if (id == "MakeA") return new A; 
    else return new C; 
}; 

在這種情況下,客戶可以撥打和複製現有的對象,像這樣:

Base * p = Base::create("IWantB"); // or std::unique_ptr<Base> ! 
Base * q = p->clone(); 

在兩種情況下客戶是否知道其中的動態類型的*p*q

+0

感謝@karrek,現在明白了。這也清除了我對靜態方法的另一種困惑。我提到的例子有虛擬功能或靜態方法。 – Sach 2012-07-20 07:17:10

1
class Base 
{ 
public: 
    Base() { } 

    virtual ~Base() { } 

    // The "Virtual Constructor" 
    static Base *Create(int id); 

    // The "Virtual Copy Constructor" 
    virtual Base *Clone() = 0; 
}; 

Base *Base::Create(int id) 
{ 

    if(id == 1) 
    { 
     return new Derived1; 
    } 
} 

class Derived1 : public Base 
{ 
public: 
    Derived1() 
    { 
     cout << "Derived1 created" << endl; 
    } 

    Derived1(const Derived1& rhs) 
    { 
     cout << "Derived1 created by deep copy" << endl; 
    } 

    ~Derived1() 
    { 
     cout << "~Derived1 destroyed" << endl; 
    } 

    Base *Clone() 
    { 
     return new Derived1(*this); 
    } 
}; 

現在,在主,當你做

void main() 
{ 
     cout << "Enter ID (1, 2 or 3): "; 
     cin >> input; 
     Base *pBase = Base::Create(input); 
     Base *pCopy = CreateCopy(pBase); 

     //Dont know what object is created but still access functions thru base pointer 
} 

Base *CreateCopy(Base *pBase) 
{ 
    return pBase->Clone(); 
} 

客戶端不需要知道它繼承的類的類型,但仍然調用一些功能。

0

最終某處某處必須知道對象的具體類型。隱藏該細節的想法導致稱爲inversion of control或更近的dependency injection的模式。

思想是在整個程序中指定一個組件,它意識到所使用的具體類型。然後它就成爲這個組件的責任來組裝你的對象圖;其他組件只將它們的依賴關係作爲接口,這些接口在構造或方法中傳遞。

C++中有一些依賴注入器實現:spring-cpp,autumnframework和dicpp浮現在腦海。我自己編寫了一個,名爲sauce,它模擬名爲guice的java框架的樣式。

0

客戶端的虛擬構造函數成語是而不是意識到派生類型。這個習慣用法的全部目的是通過基指針來克隆一個對象。這裏有一個例子:

class base 
{ 
public: 
    base* clone() 
    { 
     // NVI: implemented by derived classes. 
     do_clone(); 
    } 

protected: 
    virtual base* do_clone = 0; 
}; 

class derived : public base 
{ 
protected: 
    virtual derived* do_clone() 
    { 
     // Implementation. Note the return value is not base*. 
    } 
}; 

詳情請參見本ACCU文章:http://accu.org/index.php/journals/522

+0

不錯,但鏈接已死。 – 2016-05-25 11:00:11