c++ - 在 C++ 中链接静态库时对 ... 的 undefined reference

标签 c++ netbeans linker static-libraries

我正在将 AVL 树作为库的一部分来实现,无法确定是 CppUnit、NetBeans 8、我的 C++ 技能(模板)还是其他问题,但代码编译为静态库,但当与 CppUnit 或独立应用程序一起使用时,我得到 undefined reference to MyProject::Utilities::AVLTree<int, char>::function .

我已经尽可能地减少了代码,同时仍然保持相同的错误。

AVLTree.h

namespace MyProject {
    namespace Utilities {
        template <typename KeyType, typename ValueType> class AVLTree {
        public:
            AVLTree();
            AVLTree(const MyProject::Utilities::AVLTree<KeyType, ValueType>& orig);
            virtual ~AVLTree();
            bool hasRoot() const;
            MyProject::Utilities::AVLNode<KeyType, ValueType>* getRoot() const;

        protected:
            void setRoot(MyProject::Utilities::AVLNode<KeyType, ValueType>* _node);

        private:
            MyProject::Utilities::AVLNode<KeyType, ValueType>* _root;
            unsigned int _size;

        };
    };
};

AVL树.cpp

template <typename KeyType, typename ValueType> MyProject::Utilities::AVLTree<KeyType, ValueType>::AVLTree() {
    this->setRoot(NULL);
    this->_size = 0;
}

template <typename KeyType, typename ValueType> MyProject::Utilities::AVLTree<KeyType, ValueType>::AVLTree(const MyProject::Utilities::AVLTree<KeyType, ValueType>& orig) {
    this->setRoot(orig.getRoot());
    this->_size = orig.size();
}

template <typename KeyType, typename ValueType> MyProject::Utilities::AVLTree<KeyType, ValueType>::~AVLTree() {
    // this->clear();
}

template <typename KeyType, typename ValueType> void MyProject::Utilities::AVLTree<KeyType, ValueType>::setRoot(MyProject::Utilities::AVLNode<KeyType, ValueType>* _root) {
    this->_root = _root;
}

template <typename KeyType, typename ValueType> bool MyProject::Utilities::AVLTree<KeyType, ValueType>::hasRoot() const {
    return this->getRoot() != NULL;
}

template <typename KeyType, typename ValueType> MyProject::Utilities::AVLNode<KeyType, ValueType>* MyProject::Utilities::AVLTree<KeyType, ValueType>::getRoot() const {
    return this->_root;
}

主要.cpp

#include <cstdlib>
#include "AVLTree.h"

int main(int argc, char** argv) {
    MyProject::Utilities::AVLTree<int, char> instance;
    for (unsigned int i = 0; i < 20; ++i) {
        instance.hasRoot();
        // instance.insert(i, (char) (65 + i));
    }

    //instance.graphviz("./test.dot");
    return 0;
}

尝试构建 cppapplication_1 时 Netbeans 8 返回以下错误

g++    -c -g -I../../Documents/MyProject/src/header -MMD -MP -MF "build/Debug/GNU-Linux-x86/main.o.d" -o build/Debug/GNU-Linux-x86/main.o main.cpp
mkdir -p dist/Debug/GNU-Linux-x86
g++     -o dist/Debug/GNU-Linux-x86/cppapplication_1 build/Debug/GNU-Linux-x86/main.o -L../../Documents/MyProject/dist/Debug/GNU-Linux-x86 -lmyproject
build/Debug/GNU-Linux-x86/main.o: In function `main':
/home/.../CppApplication_1/main.cpp:6: undefined reference to `MyProject::Utilities::AVLTree<int, char>::AVLTree()'
/home/.../CppApplication_1/main.cpp:8: undefined reference to `MyProject::Utilities::AVLTree<int, char>::hasRoot() const'
/home/.../CppApplication_1/main.cpp:12: undefined reference to `MyProject::Utilities::AVLTree<int, char>::~AVLTree()'
/home/.../CppApplication_1/main.cpp:12: undefined reference to `MyProject::Utilities::AVLTree<int, char>::~AVLTree()'
collect2: error: ld returned 1 exit status

.

.

.

.

.

.

下面的代码产生了大约 100 个不同内容的错误……我并不是故意愚蠢,但对于我来说,我无法弄清楚哪里出了问题,也找不到一个工作示例或教程来解决与...一起工作

src/header/AVLTree.h:16:23: error: declaration of ‘class KeyType’
         template <typename KeyType, typename ValueType> AVLTree();
src/header/AVLTree.h:14:19: error:  shadows template parm ‘class KeyType’
     template <typename KeyType, typename ValueType> class AVLTree {
src/header/AVLTree.h:16:41: error: declaration of ‘class ValueType’
         template <typename KeyType, typename ValueType> AVLTree();
src/header/AVLTree.h:14:37: error:  shadows template parm ‘class ValueType’
     template <typename KeyType, typename ValueType> class AVLTree {
In file included from src/AVLTree.cpp:1:0:
src/header/AVLTree.h:18:23: error: declaration of ‘class KeyType’
         template <typename KeyType, typename ValueType> virtual ~AVLTree();

AVLTree.h

namespace MyProject {

    namespace Utilities {

        template <typename KeyType, typename ValueType> class AVLTree {
        public:
            template <typename KeyType, typename ValueType> AVLTree();
            template <typename KeyType, typename ValueType> AVLTree(const MyProject::Utilities::AVLTree<KeyType, ValueType>& orig);
            template <typename KeyType, typename ValueType> virtual ~AVLTree();
            template <typename KeyType, typename ValueType> bool hasRoot() const;
            template <typename KeyType, typename ValueType> MyProject::Utilities::AVLNode<KeyType, ValueType>* getRoot() const;

        protected:
            void setRoot(MyProject::Utilities::AVLNode<KeyType, ValueType>* _node);

        private:
            MyProject::Utilities::AVLNode<KeyType, ValueType>* _root;

        };
    };
};

AVLTree.cpp(指定类型)

MyProject::Utilities::AVLTree<KeyType, ValueType>::AVLTree() {
    this->setRoot(NULL);
}

MyProject::Utilities::AVLTree<KeyType, ValueType>::AVLTree(const MyProject::Utilities::AVLTree<KeyType, ValueType>& orig) {
    this->setRoot(orig.getRoot());
    // this->_size = orig.size();
}

MyProject::Utilities::AVLTree<KeyType, ValueType>::~AVLTree() {
    // this->clear();
}

void MyProject::Utilities::AVLTree<KeyType, ValueType>::setRoot(MyProject::Utilities::AVLNode<KeyType, ValueType>* _root) {
    this->_root = _root;
}

bool MyProject::Utilities::AVLTree<KeyType, ValueType>::hasRoot() const {
    return this->getRoot() != NULL;
}

MyProject::Utilities::AVLNode<KeyType, ValueType>* MyProject::Utilities::AVLTree<KeyType, ValueType>::getRoot() const {
    return this->_root;
}

AVLTree.cpp(未指定类型)

MyProject::Utilities::AVLTree::AVLTree() {
    this->setRoot(NULL);
}

MyProject::Utilities::AVLTree::AVLTree(const MyProject::Utilities::AVLTree& orig) {
    this->setRoot(orig.getRoot());
    // this->_size = orig.size();
}

MyProject::Utilities::AVLTree::~AVLTree() {
    // this->clear();
}

void MyProject::Utilities::AVLTree::setRoot(MyProject::Utilities::AVLNode<KeyType, ValueType>* _root) {
    this->_root = _root;
}

bool MyProject::Utilities::AVLTree::hasRoot() const {
    return this->getRoot() != NULL;
}

MyProject::Utilities::AVLNode<KeyType, ValueType>* MyProject::Utilities::AVLTree::getRoot() const {
    return this->_root;
}

最佳答案

模板不是函数。它们不存在于代码中。它们只是某种蓝图,或者是有关在已知所有模板参数后如何实际创建函数的说明。因此,所有模板必须驻留在头文件中,以便在知道所有模板参数后可见。 将所有模板代码从 AVLTree.cpp 移至 AVLTree.h。光搬还不行,还得改。

这是在我的 Visual Studio 上编译的示例:

namespace My {
    namespace Util {
        template <typename KeyType, typename ValueType> class World {
        public:
            World()
            {
            }

            World(const My::Util::World<KeyType, ValueType>& orig)
            {
            }

            virtual ~World()
            {
            }

            bool Hello() const
            {
                return true;
            }
        };
    };
};

使用如下代码:

My::Util::World<int, char> world;
world.Hello();

将所有函数从类声明中分离出来是可能的,但这没有实际用途,因为所有分离的代码无论如何都必须是可见的。它看起来像这样:

namespace My {
    namespace Util {
        template <typename KeyType, typename ValueType> class World {
            ....
            bool Hello() const;
        };
    };
};

template<typename KeyType, typename ValueType>
bool My::Util::World<KeyType, ValueType>::Hello() const
{
    return true;
}

我试过你的例子,它对我有用。我只是将所有函数模板放在类模板之后,并注释掉所有处理 AVLNode 的代码,然后编译。所以我原来的陈述似乎是有效的:只需将所有模板代码从源代码移动到 header 。您的第二个示例代码与您的第一个不同。你应该做的就是移动。

关于c++ - 在 C++ 中链接静态库时对 ... 的 undefined reference ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22786885/

相关文章:

c++ - 类内的前向声明(不是嵌套类)

c++ - 调试类,C++,链接器错误

c++ - 嵌入式设备上的 C/C++ CGI、POST、GET、LOGIN?

php - 无法使用 NetBeans IDE (8.1) 设置 Symfony2 框架

c++ - DLL 和完全专用的模板类

android - 在 JNI 中使用错误代码将 jbytearray 转换为 char*

java - netbeans 依赖库在更改后无法编译

netbeans - 如何设置对包含多个 jar 文件的文件夹的引用?

c++ - 修改 OBJ 文件链接到的源文件会使应用程序崩溃?

c - 如何避免c文件的重新编译?