【问题标题】:How to call a template method?如何调用模板方法?
【发布时间】:2011-05-15 07:38:00
【问题描述】:

网上有很多说明如何编写模板方法的文档,但没有太多关于如何调用它们,如何在代码中使用它们的例子。

我有一个这样的模板方法:

VectorConvertor.h

template <class T>
static void AppendToVector(std::vector<T> & VectorToBeAppended,
                           std::vector<T> & VectorToAppend);


VectorConvertor.cpp

template <class T>
void VectorConvertor::AppendToVector(std::vector<T> & VectorToBeAppended,
                                     std::vector<T> & VectorToAppend)
{
    for (std::vector::size_type i=0; i<VectorToAppend.size(); i++)
    {
        VectorToBeAppended.push_back(VectorToAppend.at(i));
    }
}

代码中的使用尝试:

std::vector<uint8_t> InputData, OutputData;
// ...
VectorConvertor::AppendToVector(OutputData, InputData);


我编译这段代码没有任何错误。但是当我尝试使用这种方法时,会出现以下错误:

错误 LNK1120:1 个未解决的外部问题

错误 LNK2019:未解析的外部符号“public: static void __cdecl VectorConvertor::AppendToVector(class std::vector > &,class std::vector > &)” (??$AppendToVector@E@VectorConvertor@@SAXAEAV? $vector@EV?$allocator@E@std@@@std@@0@Z) 在函数“public: staticclass std::vector > __cdecl Utf8::WStringToUtf8(class std::basic_string,class std::allocator >)" (?WStringToUtf8@Utf8@@SA?AV?$vector@EV?$allocator@E@std@@@std@@V?$basic_string@_WU?$char_traits@_W@std@@V?$allocator @_W@2@@3@@Z)


当我不在我的代码中使用此方法时,我不会收到任何错误消息。我在调用它时做错了什么?我错过了什么吗?


我使用的是 Visual Studio 2010 Express Edition。

【问题讨论】:

  • 没有帮助,但这些错误信息正是我停止使用 C++ 编码的原因。
  • 为清楚起见,不要将template method(这是一种设计模式)与class template member functionfunction template 混淆。

标签: c++ function templates methods


【解决方案1】:

在 C++ 中,使用模板时,您无法将 .cpp 文件中的定义分开。您需要将定义放在头文件中。见:

http://www.parashift.com/c++-faq-lite/templates.html#faq-35.12

【讨论】:

  • 该语言允许您使用 export 关键字将模板定义与其实现分开。您的编译器可能会禁止它。
  • @wilhelmtell:不幸的是,这将在 C++1x 中被弃用,这使得任何其他编译器非常不太可能会费心去实现它。 :((你不应该放牧你的 jython 缓存吗?)
  • @sbi:它实际上在 C++0x 中并没有被弃用,它被删除了(关键字仍然是关键字,但只是保留,没有任何意义)。叮咚,女巫死了等等。
  • @sbi 为什么不幸?编译器供应商应该因其辛勤工作而被称为“兼容”。如果没有人(-ish)实现export,那么这可能不是一个好主意,应该枪杀、吊死并欺负到床上。
  • @sbi:据我所知,是 EDG 最强烈地推动了它的移除。其他人都乐于继续不合规。实际上,它只能通过将整个 C++ 编译器复制到链接器中来实现(您可以省略标记器)。所以他们总是争辩说这是一个糟糕的功能,他们只是实现了它,因为他们是铁杆。可能 C++ 应该有一个更好的构建模型,可能它永远不会得到一个,但我认为导出不是。
【解决方案2】:

你需要把函数体放在头文件中。见this FAQ

【讨论】:

    【解决方案3】:

    模板链接可能会变得棘手。但最简单的解决方案通常是:

    将所有模板定义放在头文件中。

    在这种情况下,您应该将 VectorConverter.cpp 的内容移动到 VectorConverter.h(或者可能是 VectorConverter.h 底部的 #include "VectorConverter.cpp")。

    【讨论】:

      【解决方案4】:

      除了将模板函数的定义放在头文件中或包含源文件(cpp 文件)之外,您还可以为您需要的任何类型显式实例化您的函数。

      【讨论】:

        【解决方案5】:

        错误是因为试图在 CPP 文件中写入模板方法的定义。为了减少链接时间,在头文件中编写内联和模板方法的实现(定义)是一个规则。下面的代码是声明和定义模板方法的正确方式。

        VectorConvertor.h

        class VectorConvertor
        {
            public:
                template <class T>
                static void AppendToVector1(        std::vector<T> & VectorToBeAppended,
                                            const   std::vector<T> & VectorToAppend);
        
                template <class T>
                static void AppendToVector2(        std::vector<T> & VectorToBeAppended,
                                            const   std::vector<T> & VectorToAppend);
        
                template <class T>
                static void AppendToVector3(        std::vector<T> & VectorToBeAppended,
                                            const   std::vector<T> & VectorToAppend);
        
        
        }
        
        template <class T>
        void VectorConvertor::AppendToVector1(          std::vector<T> & VectorToBeAppended,
                                                const   std::vector<T> & VectorToAppend)
        {
            VectorToBeAppended.reserve(VectorToBeAppended.size() + VectorToAppend.size());
            for (std::vector<T>::size_type i=0; i<VectorToAppend.size(); i++)
            {
                VectorToBeAppended.push_back(VectorToAppend[i]);
            }
        }
        
        template <class T>
        void VectorConvertor::AppendToVector2(          std::vector<T> & VectorToBeAppended,
                                                const   std::vector<T> & VectorToAppend)
        {
            VectorToBeAppended.reserve(VectorToBeAppended.size() + VectorToAppend.size());
            for (std::vector<T>::const_iterator cit=VectorToAppend.cbegin(); cit!=VectorToAppend.cend(); ++cit)
            {
                VectorToBeAppended.push_back(*cit);
            }
        }
        
        template <class T>
        void VectorConvertor::AppendToVector3(          std::vector<T> & VectorToBeAppended,
                                                const   std::vector<T> & VectorToAppend)
        {
            VectorToBeAppended.insert(VectorToBeAppended.end(), VectorToAppend.cbegin(), VectorToAppend.cend());
        }
        

        VectorConvertor.cpp

        // Nothing to write in the CPP file.
        

        而且,这是如何在代码中使用它:

        std::vector<uint8_t> InputData, OutputData;
        // ...
        VectorConvertor::AppendToVector3(OutputData, InputData);
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-03-31
          • 1970-01-01
          • 2014-09-21
          • 2020-04-10
          相关资源
          最近更新 更多