【问题标题】:Unresolved external symbol for one specific function on class template [duplicate]类模板上一个特定函数的未解析外部符号[重复]
【发布时间】:2020-03-08 06:14:25
【问题描述】:

正如标题所述,我遇到了臭名昭著的unresolved external symbol 链接器问题。

我已经移动了.h 文件中的所有内容。模板类不再在 .h.cpp 文件之间拆分。

我已将它们包含在主文件中。我已经三四次检查了定义是否存在(显然)。

我的文件如下:

Utils.h

对于vectorvalarray 来说,这只是一个不错的选择。经过测试并且可以正常工作。

#pragma once

#include <vector>
#include <valarray>
#include <ostream>

using std::vector;
using std::valarray;
using std::ostream;


template <typename ValueType>
ostream& operator<< (ostream&, vector<ValueType>);

template <typename ValueType>
ostream& operator<< (ostream&, valarray<ValueType>);


template <typename ValueType>
ostream& operator<< (ostream& out, vector<ValueType> v)
{
    out << "Vec[";
    for (int i = 0; i < v.size() - 1; i++)
        out << v[i] << ", ";
    out << v[v.size() - 1] << "]";
    return out;
}


template <typename ValueType>
ostream& operator<< (ostream& out, valarray<ValueType> a)
{
    out << "VArr[";
    for (int i = 0; i < a.size() - 1; i++)
        out << a[i] << ", ";
    out << a[a.size() - 1] << "]";
    return out;
}

Fitness.h: 一个简单的类,有一对valarrays 和一个bool。也实现了一个漂亮的 cout。经过测试并且可以正常工作。

#pragma once

#include <valarray>
#include <ostream>

#include "Utils.h"

using std::valarray;
using std::ostream;


class Fitness {

public:
    class FitnessNotValidException : public std::exception {};
    class ValueIndexTooLargeException : public std::exception {};
    class IncorrectNewValuesLength : public std::exception {};

private:
    const valarray<double> weights;
    bool valid;
    valarray<double> values;

public:

    Fitness(const valarray<double>&);
    static Fitness max();
    static Fitness min();

    double WeightedFitness();

    const valarray<double>& Weights();

    bool Valid();
    void Valid(bool);

    void invalidate();
    void validate();

    const valarray<double>& Values();
    void Values(int, double);
    void Values(const valarray<double>&);

    double Value();
    void Value(double);

    friend ostream& operator<< (ostream&, Fitness);
};

// Implementation for everything...

ostream& operator<<(ostream & out, Fitness fit)
{
    out << "Fitness[W:" << fit.weights << ", V:" << fit.values << ", valid:" << fit.valid << "]";
    return out;
}

Individual.h: 具有Fitness 成员的模板类。还实现了“pretty-cout”。

#pragma once

#include <ostream>
#include <valarray>

#include "Fitness.h"

using std::ostream;


template <typename GeneType>
class Individual
{
private:
    Fitness fitness;
    GeneType genes;

public:

    Individual(Fitness, GeneType);

    Fitness& Fitness();

    GeneType& Genes();

    Individual<GeneType> copy();

    friend ostream& operator<< (ostream&, Individual<GeneType>);
};

// Implementation for everything...

template<typename GeneType>
ostream& operator<<(ostream& out, Individual<GeneType> ind)
{
    out << "Individual[G:" << ind.genes << ", F:" << ind.fitness << "]";
    return out;
}

所有这 3 个文件都以相同的顺序包含在主文件中。如果我尝试打印一个人的基因和健康状况,一切都很好:

Individual<valarray<int>> ind = ind_builder.build();

cout << ind.Fitness() << endl << ind.Genes() << endl;

/*
Fitness[W:VArr[1], V:VArr[0], valid:0]
VArr[0, 0, 0, 1, 0, 1, 1, 1, 0, 1]
*/

意思是&lt;&lt; 用于valarrayFitness 有效,所以我在&lt;&lt; 应该如何工作的概念上没有任何错误。但是当我尝试时:cout &lt;&lt; ind &lt;&lt; endl;

错误 LNK2019:无法解析的外部符号“类 std::basic_ostream > & __cdecl 运算符

&,class Individual >)" (??6@YAAEAV?$basic_ostream@DU?$char_traits@D@std@@@std@@AEAV01@V?$Individual@V?$valarray@H@std@ @@@@Z) 在 main 函数中引用

我看不出问题出在哪里。包含似乎是有序的,.h.cpp 之间没有拆分问题。是否有另一个我应该知道的模板陷阱?因为除了一直推荐的解决方案(例如将所有代码移动到.h 文件中)之外,我一直在寻找解决方案,但没有成功。

【问题讨论】:

标签: c++ c++11 templates visual-c++ linker


【解决方案1】:

operator &lt;&lt; 定义与operator &lt;&lt; 朋友声明不匹配,请注意operator &lt;&lt; 定义实际上是一个模板,因此不如未实现的非模板朋友首选。所以你得到链接器错误,因为编译器插入了非模板非实现友元函数的调用。 operator &lt;&lt; 也应该通过 const 限定引用获取对象。

你应该避免friend,但如果你仍然要使用它应该声明

template <typename GeneType>
class Individual;

template<typename GeneType>
ostream & operator <<(ostream &, Individual<GeneType> const & individual);

template <typename GeneType>
class Individual
{
   template<typename GeneTypeInner>
   friend ostream & operator <<(ostream &, Individual<GeneTypeInner> const & individual);
};

template<typename GeneType>
ostream & operator<<(ostream& out, Individual<GeneType> const & individual)
{
    out << "Individual[G:" << individual.genes << ", F:" << individual.fitness << "]";
    return out;
}

【讨论】:

  • 另外,对于那些想要非常详细地了解如何在模板类中使用朋友的信息的人:stackoverflow.com/questions/4660123/…
  • 天哪……那……在解释时是有道理的,尤其是@Aziuth 评论中的链接,但这似乎太复杂和不必要了。谢谢!这些额外的模板是否存在某种命名约定,只是为了满足编译器/链接器的要求?
猜你喜欢
  • 2011-08-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-18
  • 1970-01-01
  • 1970-01-01
  • 2010-11-12
  • 1970-01-01
相关资源
最近更新 更多