我决定研究/将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