我決定研究/將Head First Design Patterns的Java代碼翻譯爲C++ 11,並且我能夠使用自動內存管理實現大多數模式,這要歸功於聰明的指針。但是,我遇到了一個例子的問題。這裏是我的代碼:如何在C++中實現工廠+裝飾器模式11
#include <iostream>
#include <memory>
class AbstractBase {
public:
virtual void foo() = 0;
virtual ~AbstractBase() = default;
};
class A : public AbstractBase {
public:
void foo() override { std::cout << "Class A: foo() called" << std::endl; }
};
class B : public AbstractBase {
public:
void foo() override { std::cout << "Class B: foo() called" << std::endl; }
};
class FooDecorator : public AbstractBase {
public:
FooDecorator(AbstractBase *pBase): mpBase(pBase) { }
void foo() override
{
mpBase->foo();
++mNumberOfFooCalls;
}
static int getFooCalls() { return mNumberOfFooCalls; }
private:
static int mNumberOfFooCalls;
AbstractBase *mpBase;
};
class AbstractFactory {
public:
virtual std::unique_ptr<AbstractBase> createA() = 0;
virtual std::unique_ptr<AbstractBase> createB() = 0;
virtual ~AbstractFactory() = default;
};
class CountingFactory : public AbstractFactory {
public:
std::unique_ptr<AbstractBase> createA()
{
// auto pA = new A();
// return std::unique_ptr<AbstractBase>(new FooDecorator(pA));
std::unique_ptr<AbstractBase> pA(new A());
return std::unique_ptr<AbstractBase>(new FooDecorator(pA.get()));
}
std::unique_ptr<AbstractBase> createB()
{
// auto pB = new B();
// return std::unique_ptr<AbstractBase>(new FooDecorator(pB));
std::unique_ptr<AbstractBase> pB(new B());
return std::unique_ptr<AbstractBase>(new FooDecorator(pB.get()));
}
};
int FooDecorator::mNumberOfFooCalls = 0;
int main()
{
std::unique_ptr<AbstractFactory> pFactory(new CountingFactory());
std::unique_ptr<AbstractBase> pObjA = pFactory->createA();
std::unique_ptr<AbstractBase> pObjB = pFactory->createB();
pObjA->foo();
pObjB->foo();
std::cout << "Foo called " << FooDecorator::getFooCalls()
<< " times." << std::endl;
}
這段代碼基本上做了什麼;有兩個派生類A
和B
;他們每個人都有一個單一的成員函數來顯示哪一個被調用。還有一個名爲FooDecorator
的裝飾器,它增加了對撥打foo()
進行計數的能力。
除了這些,還有CountingFactory
這是用來直接獲得裝飾對象。
在使用這個工廠的主要部分,我創建了一個A
的實例和一個B
的實例。然後分別撥打foo()
。
當我使用鐺3.5編譯這段代碼並運行它,我沒有得到任何錯誤,但結果有點不同比預期的,因爲它要求B::foo()
兩次:
Class B: foo() called
Class B: foo() called
Foo called 2 times.
。另一方面,當我用gcc 4.9.2編譯代碼並運行它,我得到以下錯誤:
pure virtual method called
terminate called without an active exception
它看起來像問題是CountingFactory
內unique_ptr
秒。我的理解是用於初始化裝飾對象的指針被釋放,並導致未定義的行爲(clang case)或終止(gcc case)。
因此,我決定使用原始指針,並添加(以上註釋掉)行:
auto pA = new A();
return std::unique_ptr<AbstractBase>(new FooDecorator(pA));
auto pB = new B();
return std::unique_ptr<AbstractBase>(new FooDecorator(pB));
這樣做,事情順利的工作,我從兩種編譯器的預期輸出。但是,現在存在內存泄漏,並且必須刪除分配。
幾乎總是發現一個解決方案,以智能指針來解決這些問題,我正在努力想出解決這個問題的最佳方法。我也嘗試用shared_ptr
代替unique_ptr
s,但無濟於事,它不起作用。
我能否繼續使用不同方法的智能指針?或者我必須手動管理我在工廠內分配的內存(不是首選)?
@IrrationalPerson有趣,我g以上結果。可能是因爲我的蘋果叮噹3.5。 – mty