首页 文章

专业模板类的朋友(C)

提问于
浏览
3
#include <iostream>
using namespace std;
template <typename T>
class test
{
    T y;

public:
    test(T k) : y(k) {}
    friend int a(T& x);
};

template <typename T>
int a(T& x)
{
    cout << x.y;
    return 9;
}

template <>
class test<int>
{
    int y;
public:
    test(int k) : y(k) {}
    friend int a(int& x);
};

template <>
int a<int>(int& x)
{
    cout << "4";
    return 0;
}

int main(int argc, char* argv[])
{
    test<int> z(3);
    a(z);

    return 0;
}

我想创建一个测试类的朋友类(在实际情况下,它是ofstream的运算符<<) . 但我不知道如何定义专门类的模板友好功能 .

此外,上面的代码显示了此编译错误消息;

错误C2248:'test :: y':无法访问类'test'中声明的私有成员

Question added;

Aaron McDaid对我来说很好,但我试图重载运算符<< ofstream class .

friend ofstream& operator<< <test<int>> (ofstream& os, const test<int>& t);

我在上面添加了代码来测试类和

template<>
ofstream& operator<< <test<int> > (ofstream& os, const test<int>& t)
{
    os << t.y;
    return os;
}

使用上面的代码 . 但看起来我不能使用os << t.y(这是int)我不明白为什么会发生这种情况 . 错误消息是

错误C2027:使用未定义类型'std :: basic_ofstream <_Elem,_Traits>'

3 回答

  • 2

    这位朋友不是模板,而是普通的功能:

    friend int a(T& x);
    

    要拥有一个也是朋友的模板,请尝试:

    template<class U>
    friend int a(U& x);
    

    在评论中讨论之后,也许我应该表明我打算为 test 类及其专业化做出这些声明:

    template <typename T>
    class test
    {
        T y;
    
    public:
        test(T k) : y(k) {}
    
        template<class U>
        friend int a(U& x); 
    };
    
    template <>
    class test<int>
    {
        int y;
    public:
        test(int k) : y(k) {}
    
        template<class U>
        friend int a(U& x); 
    };
    

    一个轻微的缺点是,这使得所有 a 类的所有 a 函数成为朋友,但这通常不是一个大问题 .

  • 0

    Update :这是http://ideone.com/3KGU4上经过全面测试的版本 . 有关其他问题,请参阅http://ideone.com/w0dLo

    普通重载函数和模板函数之间存在差异 . 例如,在没有任何模板引用的情况下,开发人员可以声明:

    void f(int x);
    void f(char *x);
    

    或者,开发人员可以使用模板,

    template <class T> void f(T x);
    

    它们之间的主要区别在于,对于普通函数,您必须事先确定一组固定的允许参数,并且必须为每个参数提供一个实现 . 使用模板,您可以更灵活 .

    在程序的后面,很明显你希望 a 是一个模板函数,而不仅仅是一个(重载的)普通函数 . 但是当编译器第一次看到提到 a (第10行)时,看起来它正在声明一个普通的函数 . 要解决此问题,您必须执行两个步骤 . 您必须尽快声明 a 是模板函数,因此您的第一行应该是:

    template <typename T> int a(T& x);
    

    然后你必须宣布相关的友谊 . 如果 Tint ,那么 a 的参数为 test<int>& ,而不是 int& . 因此,两个朋友行应替换为:

    friend int a<test<T> >( test<T> & x); // around line 10
    friend int a<test<int> >( test<int> & x); // around line 27
    

    a 的专业化应该是:

    template <>
    int a< test<int> >(test<int>& ) // around line 30
    

    The Additional Question

    使用 ostream 而不是 ofstream (如果只输出文件而不输出 cout ,则包括 #include <fstream> ) . 在我的回答中, operator << 不是模板,而是正常的重载函数 . 我'm not sure it'可以将 operator<< 作为模板 . 此外,我在声明它并声明为朋友的地方定义了运算符 . 说实话,我认为还有其他的,可能更好的方式,但这对我有用 .

  • 4

    试试这个,it works

    #include <iostream>
    using namespace std;
    
    template <typename T>
    class test;
    
    template <typename T>
    int a( test<T>& x);
    
    template <typename T>
    class test
    {
        T y;
    
    public:
        test(T k) : y(k) {}
        friend int a<T>( test<T>& x);
    };
    
    template <typename T>
    int a( test<T>& x)
    {
        cout << x.y;
        return 9;
    }
    
    template <>
    class test<int>
    {
        int y;
    public:
        test(int k) : y(k) {}
    
        friend int a<int>( test<int> & x);
    };
    
    template <>
    int a< int >( test<int> & x)
    {
        cout << "4";
        return 0;
    }
    
    int main(int argc, char* argv[])
    {
        test<int> z(3);
        a(z);
    
        return 0;
    }
    

    问题是,模板函数 a 采用 test 模板类的参数 . 如果你想让它们都具有相同的模板参数,那么你需要明确说明IMO

    template <typename T>
        int a( test<T>& x);
    

    此函数 inttemplate<> int a(int& x) )的函数 a 的专门化也没有用 . 你需要拥有

    template <> int a<int>( test<int> & x)
    

相关问题