zoukankan      html  css  js  c++  java
  • 模板类的友元函数

    非模板友元函数


           模板类非模板友元函数是说该模板类的友元函数只是一个普通函数,并且该函数是非模板函数或该函数不视为模板函数。这里包含了两种情况,下面分别就两个例子进行说明。

    • 函数是非模板函数

           这一类友元函数特点是不带有参数列表,例如:friend void Fn()。这类友元函数通常可以用于全局对象的访问

    #include <iostream>
    using namespace std;
    
    template <class T>
    class MyNumber
    {
    private:
        T m_number;
    
    public:
        MyNumber(T number) : m_number(number) {}
        ~MyNumber() {}
    
    public:
        friend void PrintGlobalNumber();
    };
    
    MyNumber<int> g_GlobalNumber(1);
    
    void PrintGlobalNumber()
    {
        cout << "Global Number is : " << g_GlobalNumber.m_number << endl;
    }
    
    
    int main()
    {
        PrintGlobalNumber();
        return 1;
    }

    • 函数不视为模板函数

           这类友元函数通常带有参数,并且参数中含有模板类定义的类型变量,例如:friend void Fn(MyClass<T> &n)。由于我们不将该函数视为模板函数,因此对模板类的每个实例化版本都需要提供该函数的一个重载版本

           需要注意,这种用法g++编译器将会给出警告:warning: friend declaration ‘xxxx’ declares a non-template function [-Wnon-template-friend]。关闭该警告方法是加入选项-Wno-non-template-friend,例如:g++ -Wno-non-template-friend -o test test.cpp

    #include <iostream>
    using namespace std;
    
    template <class T>
    class MyNumber
    {
    private:
        T m_number;
    
    public:
        MyNumber(T number) : m_number(number) {}
        ~MyNumber() {}
    
    public:
        friend void PrintNumber(MyNumber<T> &number);
    };
    
    void PrintNumber(MyNumber<int> &number)
    {
        cout << "Int Number is : " << number.m_number << endl;
    }
    
    void PrintNumber(MyNumber<float> &number)
    {
        cout << "Float Number is : " << number.m_number << endl;
    }
    
    int main()
    {
        MyNumber<int>   n0(1   );
        MyNumber<float> n1(2.0f);
        PrintNumber(n0);
        PrintNumber(n1);
    
        return 1;
    }

     模板类的约束模板友元函数


           如果使用上面第二种方法来定义友元函数,那么局限性非常大:每当增加一个模板类的具体实例,就要相对应提供友元函数的一个重载版本。最好的办法就是应该将友元函数使用模板来实现。这里所谓的约束模板友元,指的是模板友元函数实例化取决于模板类被实例化时的类型

    • T(function) = T(class)

           这种写法是保持模板友元函数的参数类型和模板类的参数类型一致。可以将友元函数的声明和定义分开,也可以直接在模板类内部直接定义友元函数。需要注意两种实现写法上的不同。

     ▶ 友元函数声明和定义分开

    #include <iostream>
    using namespace std;
    
    // declare template function, T(function) = T(class)
    template <class T> class MyNumber;                        
    template <class T> void PrintNumber(MyNumber<T> &number); 
    
    template <class T>
    class MyNumber
    {
    private:
        T m_number;
    
    public:
        MyNumber(T number) : m_number(number) {}
        ~MyNumber() {}
    
    public:
        // declare friend function                            
        friend void PrintNumber<T>(MyNumber<T> &number);      
    };
    // function definition template <class T> void PrintNumber(MyNumber<T> &number) { cout << "The Number is : " << number.m_number << endl; } int main() { MyNumber<int> n0(1 ); MyNumber<float> n1(2.0f); PrintNumber(n0); PrintNumber(n1); return 1; }

     ▶ 友元函数直接定义在模板类内部

    #include <iostream>
    using namespace std;
    
    template <class T>
    class MyNumber
    {
    private:
        T m_number;
    
    public:
        MyNumber(T number) : m_number(number) {}
        ~MyNumber() {}
    
    public:
        friend void PrintNumber(MyNumber<T> &number)              
        {                                                         
            cout << "The Number is : " << number.m_number << endl;
        }                                                         
    };
    
    int main()
    {
        MyNumber<int>   n0(1);
        MyNumber<float> n1(2.0f);
        PrintNumber(n0);
        PrintNumber(n1);
    
        return 1;
    }

     • T(function) = class<T>

          这种写法是让模板友元函数的参数类型和模板类类型一致。

    #include <iostream>
    using namespace std;
    
    // declare template function, T(function) = class<T>
    template <class T> void PrintNumber(T &number);
    
    template <class T>
    class MyNumber
    {
    private:
        T m_number;
    
    public:
        MyNumber(T number) : m_number(number) {}
        ~MyNumber() {}
    
    public:
        // declare friend function
        friend void PrintNumber<MyNumber<T> >(MyNumber<T> &number);
    };
    
    // function definition
    template <class T>
    void PrintNumber(T &number)
    {
        cout << "The Number is : " << number.m_number << endl;
    }
    
    int main()
    {
        MyNumber<int>   n0(1   );
        MyNumber<float> n1(2.0f);
        PrintNumber(n0);
        PrintNumber(n1);
    
        return 1;
    }

     模板类的非约束模板友元函数


           这里所谓的约束模板友元,指的是友元函数的所有实例化版本都是模板类的每一个实例化版本的友元。

    • T(function) = T(class)

           这种写法是保持模板友元函数的参数类型和模板类的参数类型一致。

    #include <iostream>
    using namespace std;
    
    template <class T>
    class MyNumber
    {
    private:
        T m_number;
    
    public:
        MyNumber(T number) : m_number(number) {}
        ~MyNumber() {}
    
    public:
        template <class D>
        friend void PrintNumber(MyNumber<D> &number);
    };
    
    template <class T>
    void PrintNumber(MyNumber<T> &number)
    {
        cout << "The Number is : " << number.m_number << endl;
    }
    
    int main()
    {
        MyNumber<int>   n0(1);
        MyNumber<float> n1(2.0f);
        PrintNumber(n0);
        PrintNumber(n1);
    
        return 1;
    }

      • T(function) = class<T>

          这种写法是让模板友元函数的参数类型和模板类类型一致。

    #include <iostream>
    using namespace std;
    
    template <class T>
    class MyNumber
    {
    private:
        T m_number;
    
    public:
        MyNumber(T number) : m_number(number) {}
        ~MyNumber() {}
    
    public:
        template <class D>
        friend void PrintNumber(D &number);
    };
    
    template <class T>
    void PrintNumber(T &number)
    {
        cout << "The Number is : " << number.m_number << endl;
    }
    
    int main()
    {
        MyNumber<int>   n0(1);
        MyNumber<float> n1(2.0f);
        PrintNumber(n0);
        PrintNumber(n1);
    
        return 1;
    }
  • 相关阅读:
    2021年Mysql个税计算公式,自定义函数
    安装篇-安装mysql8
    安装篇-安装Nginx
    jsconfig.json配置Webpack别名,识别@
    Avue动态校验表单的必填校验
    renren开源把时间类型Date换为LocalDate报错
    Avue的CRUD最强封装(三)
    Avue-curd通用模板(二)
    Kalman Filter算法详解
    STM32 ADC DMA 中断模式多通道读取ADC转换值
  • 原文地址:https://www.cnblogs.com/heartchord/p/4822422.html
Copyright © 2011-2022 走看看