Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/backbone.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ CMake生成的DLL和奇怪的重复模板(C+;+;)的行为不正确_C++_Templates_Cmake - Fatal编程技术网

C++ CMake生成的DLL和奇怪的重复模板(C+;+;)的行为不正确

C++ CMake生成的DLL和奇怪的重复模板(C+;+;)的行为不正确,c++,templates,cmake,C++,Templates,Cmake,在Windows上使用CMake生成的DLL文件时,我遇到了一个令人困惑的问题。在我的库中,我使用奇怪的循环模板模式为特定类提供唯一的ID号: // da/Attribute.h: #ifndef DA_ATTRIBUTE_H #define DA_ATTRIBUTE_H namespace da { typedef unsigned int AttributeId; class AttributeBase { public: virtual AttributeId getTyp

在Windows上使用CMake生成的DLL文件时,我遇到了一个令人困惑的问题。在我的库中,我使用奇怪的循环模板模式为特定类提供唯一的ID号:

// da/Attribute.h:

#ifndef DA_ATTRIBUTE_H
#define DA_ATTRIBUTE_H

namespace da {

typedef unsigned int AttributeId;

class AttributeBase {
public:
    virtual AttributeId getTypeId() const=0;

protected:
    /** Static ID counter.  Every class that derives da::AttributeBase is
        assigned an increment of this counter as its type ID number */
    static AttributeId sNextId;

};

template <class Derived>
class Attribute : public AttributeBase {
private:
    static AttributeId msTypeId;

public:
    Attribute() {
        if (msTypeId == 0) {
            msTypeId = ++sNextId;
        }
    }

    virtual ~Attribute() {

    }

    /** For static contexts */
    static AttributeId typeId() {
        if (msTypeId == 0) {
            msTypeId = ++sNextId;
        }

        return msTypeId;
    }

    AttributeId getTypeId() const {
        return typeId();
    }

};

template <class Derived> AttributeId Attribute<Derived>::msTypeId = 0;

}

#endif
运行GDB时,在Foo::getTypeID()中有一个中断,我发现“msTypeId”和“Foo::msTypeId”有不同的内存地址。到底是什么

但是,只有在DLL中定义了Foo时,才会发生这种情况。(显然,只有在Windows 7中——我的Debian构建中没有这个问题)如果我在main.cpp中创建派生类,或者如果我只是将库中的所有代码编译到可执行文件中,完全跳过DLL步骤,那么它就可以正常工作

所有内容都使用MSYS和MinGW编译,在Windows7 Home Premium上使用GCC4.7

这是图书馆的CMakeLists.txt,以防我在那里搞砸了:

cmake_minimum_required(VERSION 2.6)
project(foo)

add_definitions(-std=c++0x)
set(CMAKE_BUILD_TYPE Debug)

set(sources
    Foo.cpp
)

add_library(foo SHARED ${sources})

您必须从共享库导出类型。这是使用装饰器完成的。通读MSDN文档;这相当复杂

由于在构建库时头需要有
\uuudeclspec(dllexport)
,在编译使用它的代码时头需要有
\udeclspec(dllimport)
,因此通常定义一个符号,通常称为
LIBRARYNAME\u EXPORT
,如果根据是否定义了
LIBRARYNAME\u EXPORTS
来定义它

CMake在构建(共享)库时自动定义导出的目标。可以通过设置
DEFINE_SYMBOL
target属性来覆盖它

Unix选择一个不同的路径,默认情况下导出并导入共享库中的所有符号(静态和显式隐藏的符号除外)。这会带来一点性能损失,因为需要解决更多的符号,但使用起来更容易(从静态库切换到共享库不需要更改),而且更灵活(即,您可以覆盖共享库中的符号,这在Windows中是无法做到的)

// main.cpp
Foo *foo = new Foo;    

Foo->getTypeId() == 1 // True
Foo::typeId() == 1 // Should be true, but isn't.  Foo::typeId() == 2
cmake_minimum_required(VERSION 2.6)
project(foo)

add_definitions(-std=c++0x)
set(CMAKE_BUILD_TYPE Debug)

set(sources
    Foo.cpp
)

add_library(foo SHARED ${sources})