如果函数在.cpp中实现,则为c ++链接错误

时间:2014-01-06 00:23:59

标签: c++ static singleton linker-errors

如果我在.cpp中实现类的create方法,我得到

错误LNK2019:未解析的外部符号“protected:__thiscall Singleton :: Singleton(void)”(?? 0Singleton @@ IAE @XZ)在函数“public:static void __cdecl Singleton :: create(void)”中引用(?创建@ @@辛格尔顿SAXXZ

但是,如果我在头文件中实现该方法,则编译时没有任何错误:S

头文件

 #pragma once
 #include <iostream>
class Singleton
{
 public:

static Singleton * getInstance()
{
    return s_instance;
}

static void create();
static void destroy();

void help();

protected:

static Singleton * s_instance;
Singleton();
};

源文件:

#include "Singleton.h"

Singleton * Singleton::s_instance = NULL;

 void Singleton::create()
{
    if (!s_instance)
    {
         s_instance = new Singleton;
    }
}



void Singleton::destroy()
{
    delete s_instance;
    s_instance = NULL;
}

但是如果我在头部内实现create方法,它不会抛出任何错误

在其中实现create方法的头文件

#pragma once
#include <iostream>
class Singleton
{
public:

    static Singleton * getInstance()
    {
        return s_instance;
    }

    static void create(){
        if (!s_instance)
        {
            s_instance = new Singleton;
        }
    }
    static void destroy();


protected:

    static Singleton * s_instance;
    Singleton();
};

2 个答案:

答案 0 :(得分:3)

在cpp中,你的create函数试图通过使用new运算符初始化Singleton,但是你没有给它一个构造函数。尝试向Singleton()提供实施。即:

protected:

    static Singleton * s_instance;
    Singleton() {}
};

答案 1 :(得分:0)

问题。

您已声明一个默认构造函数,并且您正在使用它(在new表达式中),但您尚未实现它。

修复

只需删除构造函数声明:

protected:

    static Singleton * s_instance;
    // Singleton();  -- don't have this. Remove it.
};

其他事项。

使用protected特性,该类是为继承而设计的,那么如何确保派生类只能通过单例机制实例化?

嗯,你没有太多控制派生类,所以最简单只是为了记录每个派生类应该声明和定义一个非public默认构造函数。

但是,基于必须由派生程度最高的类初始化虚拟基础这一事实,可以使用一种技巧来强制执行此操作。这可以用来强制客户端代码在底部添加最终的类派生。其中大多数派生类是模板实例化,它定义了非公共构造函数。

更实际的替代方案是将事情颠倒过来。

也就是说,不是将Singleton类设计为派生(由受保护的东西发出信号),而是将其设计为继承自客户端代码类。这意味着使用模板。 Andrei Alexandrescu在他的经典着作“现代C ++设计”中讨论了一些使用这种思想的单身方法。