我正在尝试同时实现Singleton Pattern和Factory Pattern。
在我看来,每种工厂只能有一个基于抽象类的工厂,并使用工厂生成相应的shape
对象。
但我收到了一个错误:
错误LNK2001:未解析的外部符号“private:static class TriangleFactory * TriangleFactory :: instance”(?instance @ TriangleFactory @@ 0PAV1 @ A)
我不知道为什么会这样。你能告诉我如何解决这个问题吗? 代码如下。
#include<type_traits>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<memory>
#include<time.h>
using namespace std;
class Shape
{
public:
virtual void display();
protected:
int x, y;
};
class MyTriangle:public Shape
{
public:
MyTriangle(int _x, int _y)
{
x = _x;
y = _y;
}
MyTriangle()
{
x = rand() % 200;
y = rand() % 200;
}
void display()
{
printf("%d %d\n",x,y);
}
};
class SuperFactory
{
public:
virtual Shape* Execute() = 0;
};
class TriangleFactory :public SuperFactory
{
public:
Shape* Execute()
{
Shape *p = new MyTriangle;
return p;
}
static SuperFactory* GetFactory()
{
return instance;
}
private:
TriangleFactory()
{
instance = nullptr;
instance = new TriangleFactory;
}
~TriangleFactory(){}
static TriangleFactory* instance;
};
int main()
{
MyTriangle *p = dynamic_cast<MyTriangle*>(TriangleFactory::GetFactory()->Execute());
p->display();
return 0;
}
非常感谢您的回答:)
答案 0 :(得分:4)
我的批评:
您不需要所有这些#include
。您只能使用<iostream>
。
您的构造函数和解构函数是私有的。我建议你:a。)使它们受到保护,而b。)只使构造函数成为私有的。解构器应该是公共的和虚拟的。
函数Shape::display
应声明为纯SuperFactory::Execute
的虚函数。将其更改为:virtual void display() = 0;
其他答案的主要问题 - 只需在TriangleFactory* TriangleFactory::instance;
函数之前写main()
就是这样:你会发现自己面临一个可爱的空指针错误。解决方案需要改变你的单身人士。因为您在构造函数中初始化instance
,并且在您发布的代码中没有创建类型TriangleFactory
的对象,所以永远不会调用构造函数,并且永远不会初始化instance
。
我的解决方案:
继续使用TriangleFactory* TriangleFactory::instance;
功能之前的main()
,但将其值设置为null,如TriangleFactory* TriangleFactory::instance = nullptr;
。这样做可以避免与过去的内存泄漏有关的错误。
不要在构造函数中初始化instance
,而是将构造函数保留为空并将GetFactory
函数更改为:
static SuperFactory *GetFactory()
{
if(!instance)
{
instance = new TriangleFactory();
return instance;
}
else
{
return instance;
}
}
现在,为什么我会在TriangleFactory *TriangleFactory::instance = new TriangleFactory();
main()
之前改变所有这一切 - 我怀疑你做了 - 工作得很好?好吧,初始化函数之外的任何数据都是有风险的。这些对象在运行时以任意顺序创建 - 当您开始创建依赖于其他类的类时,TriangleFactory *TriangleFactory::instance = new TriangleFactory();
会在您的脸上爆炸。不要在你的脸上炸掉东西。 Get rid of cable and upgrade to DirecTV。没有xD开玩笑,但绝对不做TriangleFactory *TriangleFactory::instance = new TriangleFactory();
答案 1 :(得分:1)
该行:
static TriangleFactory* instance;
声明实例。没有定义。添加:
TriangleFactory* TriangleFactory::instance;
这将定义链接器的符号。
答案 2 :(得分:1)
您需要输入以下行。
TriangleFactory* TriangleFactory::instance;
错误消息告诉您编译器找不到定义实例。当您将其用作类成员变量时,需要初始化静态成员变量 instance 。
答案 3 :(得分:1)
在c ++中正确启动单例的方法是使用静态实例,而不是静态指针。这样,对象将在程序退出时被正确销毁。
因此GetFactory()
的正确外观将是:
static SuperFactory * GetFactory(){
static TriangleFactory factory;
return &factory;
}
factory
实例将在首次使用GetFactory()
时创建,并在程序退出时销毁。没有内存泄漏和最简单的解决方案。