首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >未解决的外部因素-联系问题

未解决的外部因素-联系问题
EN

Stack Overflow用户
提问于 2020-06-25 02:05:21
回答 1查看 39关注 0票数 0

目前正在为c++上一门课程,有一个关于模板类和函数的项目--得到了这个错误,msg不知道从哪里来,所有的文件都编译得很好。经过复核的所有声明等

ERROR MSG: Menu.obj : error LNK2019:未解析的外部符号“类std::basic_ostream& __cdecl operator<<”(class std::basic_ostream &,类CSet const &)“函数中引用的CSet”私有: bool __thiscall菜单::CSet(Void)“(?check@Menu@@AAE_NXZ)

代码: CSET//一组类型t,头文件

代码语言:javascript
复制
#ifndef __C_SET_H__
#define __C_SET_H__
#include <iostream>
using namespace std;

template <class T>
class CSet
{
public:
    CSet() { m_length = 0; m_setArr = NULL; }//ctor
    CSet(const CSet& set);//cctor
    ~CSet() { delete[] m_setArr; }

    //--operators--//
    CSet& operator=(const CSet& );
    CSet& operator+=(const T& );
    CSet& operator-=(const T& );
     CSet& operator-(const CSet& )const;

    friend ostream& operator<<(ostream&, const CSet& );//ouput

    //--methods--//
    const CSet UNION(const CSet& );
    const CSet INTERSECT(const CSet& );

private:
    int m_length;
    T* m_setArr;

     int appears(const T& );//private method check index of T in setArr


};



template <class T>
CSet<T>::CSet(const CSet& set)//cctor
{
    *this = set;
}

template <class T>
CSet<T>& CSet<T>::operator=(const CSet& set)
{
    m_length = set.m_length;
    m_setArr = set.m_setArr;
    return *this;
}

template <class T>
CSet<T>& CSet<T>::operator+=(const T& val)
{
    if (appears(val) == -1)
        return *this;
    try
    {
        T* arr = new T[m_length + 1];
        for (int i = 0; i < m_length; i++)
            arr[i] = m_setArr[i];
        arr[m_length] = val;
        m_length++;
        delete[] m_setArr;
        m_setArr = arr;
        return *this;
    }
    catch (bad_alloc)
    {
        cout << "Memory Allocation Failed!" << endl;
        return *this;
    }
    
}

template <class T>
CSet<T>& CSet<T>::operator-=(const T& val)
{
    int index = appears(val);
    if (index == -1)
        return *this;
    m_length--;
    try
    {
        T* arr = new T[m_length];
        int j = 0;//index
        for (int i = 0; i < m_length; i++)
        {
            if (i == index)
                continue;
            arr[j] = m_setArr[i];
            j++;
        }
        delete[] m_setArr;
        m_setArr = arr;
        return *this;
    }
    catch (bad_alloc)
    {
        cout << "Memory Allocation Failed!" << endl;
        return *this;
    }
}

template <class T>
 CSet<T>& CSet<T>::operator-(const CSet& set)const
{

    CSet copy;
    copy.m_length = m_length;
    copy.m_setArr=m_setArr;
    copy.INTERSECT(set);
    CSet copy2=set;
    for (int i = 0; i < copy.m_length; i++)
        copy2.operator-=(copy.m_setArr[i]);
    return copy2;
}

template <class T>
ostream& operator<<(ostream& os, const CSet<T>& set)
{
    if (set.m_length == 0)
        os << "The set is empty!" << endl;
    else{
        os << '(';
        int i;
        for (i = 0; i < set.m_length - 1; i++)
            os << set.m_setArr[i] << ',';
        os << set.m_setArr[i] << ')' << endl;
    }
    return os;
}

template <class T>
const CSet<T> CSet<T>::UNION(const CSet& set)
{
    CSet copy;
    copy.m_length = m_length;
    copy.m_setArr = m_setArr;
    for (int i = 0; i < set.m_length; i++)
        copy.operator+=(set.m_setArr[i]);
    return copy;
}

template <class T>
const CSet<T> CSet<T>::INTERSECT(const CSet& set)//private
{
    CSet copy;
    copy.m_length = m_length;
    copy.m_setArr = m_setArr;
    for (int i = 0; i < set.m_length; i++)
        copy.operator-=(set.m_setArr[i]);
    return copy;
}

template <class T>
 int CSet<T>::appears(const T& val)//private
{
    for (int i = 0; i < m_length; i++)
        if (m_setArr[i] == val)
            return i;
    return -1;

}

#endif

设置H文件的菜单//打印和显示菜单

代码语言:javascript
复制
#ifndef __MENU_H__
#define __MENU_H__
#include"CSet.h"
#include <iostream>
using namespace std;
class Menu
{
public:
    Menu();//prints menu
private:
    //--members--//
    CSet<long> longSet;
    CSet<char> chSet1;
    CSet<char> chSet2;
    CSet<string> strSet;
    //--methods--//
    bool check();
    void printSetsOp();
    void addRemoveElement(bool);
    void difference();

};
#endif

MENU.CPP

代码语言:javascript
复制
#include "Menu.h"
#include "CSet.h"
#include <iostream>
using namespace std;

Menu::Menu()
{//menu print
    do {
        //show the menu until the user wants to exit
        cout << "================MENU================" << endl;
        ...
    } while (check());//as long as the user doesnt want to exit
}

bool Menu::check()
{
    int choice;
    cin >> choice;//user input
    switch (choice)
    {
    case 1:
    {
        ...
        return true;//keep the menu loop going
    }
    .
    .
    .
    case 7:
    {//exit
        cout << "Goodbye!" << endl;
        return false;//exit the program
    }
    default:
    {//invalid number
        cout << "please enter a valid number!" << endl;
        return true;//keep the menu loop going
    }
    }
}

void Menu::printSetsOp()
{
    //print options
}

void Menu::addRemoveElement(bool add)
{
    printSetsOp();//print scnd menu
    int choice;
    cin >> choice;//which set
    switch (choice)
    {
    case 1:
    {//add or remove elements, each type seperatly
        long elm;
        cout << "Insert number =  ";
        cin >> elm;
        add ? longSet.operator+=(elm) : longSet.operator-=(elm);
        return;
    }
    case 2:
    case 3:
    {
        char ch;
        cout << "Insert character =  ";
        cin >> ch;
        if (add)
            (choice == 2) ? chSet1.operator+=(ch) : chSet2.operator+=(ch);
        else
            (choice == 2) ? chSet1.operator-=(ch) : chSet2.operator-=(ch);
        return;
    }
    default:
    {//invalid number
        cout << "please enter a valid number!" << endl;
        return;//keep the menu loop going
    }
    }
}

不知道是什么导致了这个错误,所以几乎所有的东西都贴了出来。谢谢

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-06-25 02:48:38

问题是,你的CSet的朋友operator<<命名了一个不同于你的模板operator<<的函数,这实际上声明了一个新的非模板函数,它最终是一个比模板函数更好的候选函数,但是没有定义这样的函数,因此出现了链接错误。

您可以通过使朋友声明引用此操作符对特定CSet<T>的完全专门化来解决这一问题。为此,模板函数必须已经声明,这需要CSet的前向声明。所以,你会做这样的事情:

代码语言:javascript
复制
template <class T> class CSet;

template <class T>
ostream& operator<<(ostream& os, const CSet<T>& set)
{
    // implementation here
}

template <class T>
class CSet {
    // all of your other stuff...

    // Add <> to have the friend declaration refer to a specific operator<< instantiation
    // With <>, T is deduced. You can also say <T> instead.
    friend ostream& operator<< <>(ostream&, const CSet& );
};

请注意,当您在模板类型中声明非模板朋友函数时,大多数编译器都应该警告您,因为它会导致所遇到的问题。确保启用了编译器警告。

代码语言:javascript
复制
warning: friend declaration 'std::ostream& operator<<(std::ostream&, const foo<T>&)' declares a non-template function
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62566782

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档