【问题标题】:template class, friend operator << overload模板类,友元运算符 << 重载
【发布时间】:2011-05-08 00:55:43
【问题描述】:

我正在尝试为模板类重载“

/tmp/ccjJIJhO.o: In function `main':
main.cpp:(.text+0xad): undefined reference to `std::basic_istream<char, std::char_traits<char> >& operator>><int>(std::basic_istream<char, std::char_traits<char> >&, FeatureVector<int>&)'
main.cpp:(.text+0xba): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& operator<< <int>(std::basic_ostream<char, std::char_traits<char> >&, FeatureVector<int> const&)'
collect2: ld returned 1 exit status

类定义:

common.h

#include <iostream>
using namespace std;

特征向量.h

#ifndef FEATURE_VECTOR_H
#define FEATURE_VECTOR_H

#include <common.h>

template < class FEAT_TYPE >
class FeatureVector;

template < class FEAT_TYPE >
istream & operator >> (istream &, FeatureVector<FEAT_TYPE> &);

template < class FEAT_TYPE >
ostream & operator << (ostream &, const FeatureVector<FEAT_TYPE> &);

template < class FEAT_TYPE >
class FeatureVector{
    public:
        FeatureVector(int = 0);
        ...
        friend istream & operator >> <>(istream &, FeatureVector<FEAT_TYPE> & );
        friend ostream & operator << <>(ostream &, const FeatureVector<FEAT_TYPE> &);
        ...
        ~FeatureVector();

    private:
        int m_nDim;
        FEAT_TYPE * m_pFeat;
};
#endif

特征向量.cpp

#include <featurevector.h>
...
template < class FEAT_TYPE >
istream & operator >> (istream & input, FeatureVector< FEAT_TYPE> & refFeat ){

    int d;

    for(d=0; d < refFeat.getDim(); d++){
        input >> refFeat.m_pFeat[d];
    }

    return (input);
}

template < class FEAT_TYPE >
ostream & operator << (ostream & output, const FeatureVector< FEAT_TYPE > & refFeat ){

    int d;

    for(d=0; d < refFeat.getDim(); d++){
        output << refFeat.m_pFeat[d] << " ";
    }

    output << endl;

    return (output);
}
...
#include "featurevector-impl.cpp"

特征向量-impl.cpp

template class FeatureVector<int>;
//template istream & operator >> <>(istream &, FeatureVector<int> &);
//template ostream & operator << <>(ostream &, const FeatureVector<int> &);

mylib.h

#ifndef MY_LIB_H
#define MY_LIB_H
#include <featurevector.h>
#endif

main.cpp

#include <mylib.h>
#include <common.h>

int main(){
    FeatureVector<int> pFeat(10);
    cin >> (pFeat);
    cout << (pFeat);

    return (0);
}

与“mylib”关联的Makefile

INC=./inc
SRC=./src
LIB=./lib
OBJ=./obj

CC=g++
CFLAGS=-O3 -Wall

mylib: $(LIB)/mylib.a
echo "mylib was created!..."

$(LIB)/mylib.a: \
$(OBJ)/featurevector.o 
    ar csr $(LIB)/mylib.a \
$(OBJ)/featurevector.o 

$(OBJ)/featurevector.o: $(SRC)/featurevector.cpp
    $(CC) -c $(CFLAGS) $(SRC)/featurevector.cpp -I$(INC)  \
    -o $(OBJ)/featurevector.o

clean:
    rm -rf $(LIB)/*.a
    rm -rf $(OBJ)/*.o

main.cpp 的 Makefile(main.cpp 及其 Makefile 位于“app”目录下)

LIB=../lib
INC=../inc
OBJ=../obj
BIN=../bin

CC=g++
CFLAGS=-O3 -Wall
LFLAGS=-lmylib -lm

$@.cpp: $(LIB)/mylib.a $@.cpp
    cd ..; make; cd app;
$(CC) $(CFLAGS) $@.cpp -o $(BIN)/$@ -I$(INC) -L$(LIB) $(LFLAGS)

clean:
    rm -rf $(BIN)/*

【问题讨论】:

  • friend ostream & operator 这是错字吗?
  • 是否是相同的代码造成了错误?错误在运算符 >> 而不是
  • 工作正常:ideone.com/H9xjs
  • 大家好,我编辑了原始帖子并包含了实际代码。
  • 永远不要从头文件中#include .cpp 文件。只需不同的名称:blah_detail.hpp、_blah.inc 等。

标签: c++ class templates operator-overloading


【解决方案1】:

根据this,您必须在类定义中将该函数称为模板。

class.h

#include <iostream>
using std::ostream;

template <typename T>
class A {
  public:
    ...

    template <typename J> // <-- CAUTION!
    friend ostream &operator<<(ostream &output, const A<J> &a);
};

class.cpp

#include "class.h"
...
template <typename T>
ostream &operator<<(ostream &output, const A<T> &a) {
  // Your implementation
  return output;
}

...
template ostream &operator<<(ostream &output, const A<int> &a);
template ostream &operator<<(ostream &output, const A<float> &a);

如果去掉template &lt;typename J&gt;这行,就会出现编译错误“underfined reference”。

【讨论】:

    【解决方案2】:

    【讨论】:

    • 我不认为这是问题所在。 Javier 是 #include- 直接从 H 文件中获取 HPP 文件,产生的结果与您的常见问题解答链接相同。
    • 没错,我已经考虑过引用链接中的建议。还是谢谢。
    • @John, @Jahvier:我看不到operator&gt;&gt; 函数模板的定义在main 中可用。我也看不到它的明确实例化。如果是的话,对不起,噪音。但我认为如果是这样,就不会提出这个问题。干杯,
    • 我编辑了类,所以已经包含了运算符>>的定义。
    • @Javier:好吧,告诉我们这是否解决了问题,如果没有,发布一些实际代码?
    【解决方案3】:

    您发布的错误代码表明是operator&gt;&gt; 引发了未解决的外部错误,而不是operator&lt;&lt;。此外,您的代码不会编译,因为myClass 上没有转换构造函数采用int。所以你没有发布正确的代码。

    但这有效:

    #include <iostream>
    using namespace std;
    
    template < class T >
    class myClass;
    
    template < class T >
    ostream & operator << (ostream &, const myClass<T> &);
    
    template < class T >
    class myClass{
        public:
            myClass(int) {}
            friend ostream & operator << <>(ostream &, const myClass<T> &);
    
        private:
            T m_Data;
    };
    
    template < class T >
    ostream & operator << (ostream & out, const myClass<T> & refClass){
        out << refClass.m_Data << endl;
        return (out);
    }
    
    myClass<int>;
    myClass<float>;
    
    
    
    int main(int argc, char **argv){
        myClass<int> test(5);
        cout << test;
        return 0;
    }
    

    【讨论】:

    • 嗨,正如我提到的,我没有把整个类定义。我当然有一个默认构造函数。那么,您的建议是将所有内容放在同一个文件中吗?这是问题吗?出于组织目的,我更喜欢将文件分开。
    • @Javier:不,最终遇到的问题是您发布的错误消息抱怨operator&gt;&gt;,而不是operator&lt;&lt;
    • @Javier:另外,如果您可以发布一个最小且完整的示例来复制您遇到的问题,那将会非常有帮助。您发布的伪代码很难使用。
    • 嗨,约翰,我已经更新了课程,因为我试图同时重载“>>”和“
    【解决方案4】:

    别把事情搞得这么复杂:

    template<class FEAT_TYPE>
    struct FeatureVector {
      FeatureVector(int = 0);
    
      friend std::istream& operator>>(std::istream &s, FeatureVector &x) {
        for(int d = 0; d < x.getDim(); d++) {
          s >> x.m_pFeat[d];
        }
        return s;
      }
    
      friend std::ostream& operator<<(std::ostream &s, FeatureVector const &x) {
        // since you're terminating with " " rather than separating:
        copy(x.m_pFeat, x.m_pFeat + x.getDim(), ostream_iterator<FEAT_TYPE>(s, " "));
        s << endl;
        return s;
      }
    
      //...
    

    【讨论】:

    • 感谢您的建议!但由于某些原因,我需要使用类。
    • @Javier: 'struct' 声明了一个类。
    • @Roger:谢谢,我不知道。我的方法哪里出了问题,我不明白哪里出了问题。
    • @Javier:我不确定到底是什么问题,因为问题已经更新了更多信息,我不愿意假设知道你在使用什么,但作为问题文本现在,这些函数的定义被注释掉了。 — 我的回答是说你让这非常太复杂了,并展示了如何避免这种情况。
    【解决方案5】:

    featurevector-impl.cpp 不正确。显式模板实例如下所示:

    template class FeatureVector<int>;
    

    由于操作符不是成员,它们也必须被显式实例化:

    template istream & operator >> <>(istream &, FeatureVector<int> &);
    

    不过,我不建议您像这样拆分模板定义,除非您真的热衷于微观管理哪些特定类将与您的模板一起使用(这与使用模板的精神背道而驰)。

    【讨论】:

    • 嗨史蒂夫,我最近尝试了你的建议,但我仍然有同样的错误。我更新了我最初的帖子,我是否包括了真正的课程。
    • 你的编译命令是什么?您是否同时编译 main.cpp 和 featurevector.cpp? (或者 main.o 和 featurevector.o 如果你分别编译它们)
    • @Steve,我正在分别编译它们。
    • @Javier:那么当您链接它们时,您是否在命令中指定了两个目标文件?如果我将流运算符的显式实例化放在 featurevector-impl.cpp 中,这将为我编译、链接和运行(即使是单独编译)。
    • 嗨,史蒂夫,我基本上有一个包含特征向量类的小库(因此,我此时生成了 featurevector.o)。然后,当我编译主程序时,我链接库……,例如: g++ -O3 -Wall main.cpp -o ../bin/main -I../inc -L../lib -lmylib -lm
    猜你喜欢
    • 2021-05-18
    • 2011-06-07
    • 2010-11-20
    • 2011-04-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多