2014.10.9 模板函数做友元函数的问题

1.模板函数作为类的友元函数,要先声名。

2.在类的定义中声明友元时要在函数后加上<T>

  1 #ifndef Array1D_
  2 #define Array1D_
  3
  4 // One-dimensional arrays.
  5
  6 #include <iostream>
  7 #include "xcept.h"
  8
  9
 10 template <class T> class Array1D;
 11 //template <class T> std::istream &operator>>(std::istream &in, Array1D<T> &r);//函数模板做友元要先声明
 12 template <class T> std::ostream& operator<<(std::ostream&, const Array1D<T>&);
 13
 14 template<class T>
 15 class Array1D {
 16    friend std::ostream& operator<<<T>
 17           (std::ostream&, const Array1D<T>&);
 18    public:
 19       Array1D(int size = 0);
 20       Array1D(const Array1D<T>& v); // copy constructor
 21       ~Array1D() {delete [] element;}
 22       T& operator[](int i) const;
 23       int Size() {return size;}
 24       Array1D<T>& operator=(const Array1D<T>& v);
 25       Array1D<T> operator+() const; // unary +
 26       Array1D<T> operator+(const Array1D<T>& v) const;
 27       Array1D<T> operator-() const; // unary minus
 28       Array1D<T> operator-(const Array1D<T>& v) const;
 29       Array1D<T> operator*(const Array1D<T>& v) const;
 30       Array1D<T>& operator+=(const T& x);
 31       Array1D<T>& ReSize(int sz);
 32    private:
 33        int size;
 34        T *element; // 1D array
 35 };
 36
 37 template<class T>
 38 Array1D<T>::Array1D(int sz)
 39 {// Constructor for one-dimensional arrays.
 40    if (sz < 0) throw BadInitializers();
 41    size = sz;
 42    element = new T[sz];
 43 }
 44
 45 template<class T>
 46 Array1D<T>::Array1D(const Array1D<T>& v)
 47 {// Copy constructor for one-dimensional arrays.
 48    size = v.size;
 49    element = new T[size];  // get space
 50    for (int i = 0; i < size; i++) // copy elements
 51       element[i] = v.element[i];
 52 }
 53
 54 template<class T>
 55 T& Array1D<T>::operator[](int i) const
 56 {// Return reference to element i.
 57    if (i < 0 || i >= size) throw OutOfBounds();
 58    return element[i];
 59 }
 60
 61 template<class T>
 62 Array1D<T>& Array1D<T>::operator=(const Array1D<T>& v)
 63 {// Overload assignment operator.
 64    if (this != &v) {// not self-assignment
 65       size = v.size;
 66       delete [] element; // free old space
 67       element = new T[size]; // get right amount
 68       for (int i = 0; i < size; i++) // copy elements
 69          element[i] = v.element[i];
 70       }
 71    return *this;
 72 }
 73
 74 template<class T>
 75 Array1D<T> Array1D<T>::
 76            operator+(const Array1D<T>& v) const
 77 {// Return w = (*this) + v.
 78    if (size != v.size) throw SizeMismatch();
 79
 80    // create result array w
 81    Array1D<T> w(size);
 82    for (int i = 0; i < size; i++)
 83        w.element[i] = element[i] + v.element[i];
 84
 85    return w;
 86 }
 87
 88 template<class T>
 89 Array1D<T> Array1D<T>::
 90            operator-(const Array1D<T>& v) const
 91 {// Return w = (*this) - v.
 92    if (size != v.size) throw SizeMismatch();
 93
 94    // create result array w
 95    Array1D<T> w(size);
 96    for (int i = 0; i < size; i++)
 97        w.element[i] = element[i] - v.element[i];
 98
 99    return w;
100 }
101
102 template<class T>
103 Array1D<T> Array1D<T>::operator-() const
104 {// Return w = -(*this).
105    // create result array w
106    Array1D<T> w(size);
107    for (int i = 0; i < size; i++)
108        w.element[i] = -element[i];
109
110    return w;
111 }
112
113 template<class T>
114 Array1D<T> Array1D<T>::operator*(const Array1D<T>& v) const
115 {// Return w = (*this) * v. Pairwise multiply.
116    if (size != v.size) throw SizeMismatch();
117
118    // create result array w
119    Array1D<T> w(size);
120    for (int i = 0; i < size; i++)
121        w.element[i] = element[i] * v.element[i];
122
123    return w;
124 }
125
126 template<class T>
127 Array1D<T>& Array1D<T>::operator+=(const T& x)
128 {// Add x to each element of (*this).
129    for (int i = 0; i < size; i++)
130        element[i] += x;
131    return *this;
132    }
133
134 template<class T>
135 std::ostream& operator<<(std::ostream& out,
136                     const Array1D<T>& x)
137 {// Put the elements of x into the stream out.
138    for (int i = 0; i < x.size; i++)
139       out << x.element[i] << "  ";
140    return out;
141 }
142
143 template<class T>
144 Array1D<T>& Array1D<T>::ReSize(int sz)
145 {// Change the size to sz.
146  // Do not copy array elements to new space.
147    if (sz < 0) throw BadInitializers();
148    delete [] element;
149    size = sz;
150    element = new T [size];
151    return *this;
152 }
153
154 #endif

以上为本次实验的实例代码,由于没有先进行声明,编译可以通过,执行时会报错

code block:对‘operator<<(std::ostream&, Array1D<int> const&)’未定义的引用VS:error LNK2019: 无法解析的外部符号

时间: 2024-10-11 01:49:53

2014.10.9 模板函数做友元函数的问题的相关文章

在复数类模板中使用友元函数实现复数相加

程序代码(这段代码在vc6.0中不能编译通过,在VS中能编译通过) <span style="font-size:18px;">#include <iostream> using namespace std; template<class T>//类声明前加模板的声明 class Complex { public: Complex( ) { real=0; imag=0; } Complex(T r,T i) { real=r; imag=i; }

在c++ 模板类外写 操作符重载函数,并且是模板类的友元函数

看视频教程说不能在c++ 模板类外写 操作符重载函数,并且是模板类的友元函数 我试了试,可以,放出测试代码: #include <iostream> using namespace std; template<typename T> class A { public: A(T a) { this->a = a; } template<typename T> //加上这句就可以了 friend A<T> operator+(A<T> &

模板类的友元函数

非模板友元函数 模板类的非模板友元函数是说该模板类的友元函数只是一个普通函数,并且该函数是非模板函数或该函数不视为模板函数.这里包含了两种情况,下面分别就两个例子进行说明. • 函数是非模板函数 这一类友元函数特点是不带有参数列表,例如:friend void Fn().这类友元函数通常可以用于全局对象的访问. #include <iostream> using namespace std; template <class T> class MyNumber { private:

运算符重载三种形式(成员函数,友元函数,普通函数)详解

首先,介绍三种重载方式: 1 //作为成员函数重载(常见) 2 class Person{ 3 Private: 4 string name; 5 int age; 6 public: 7 Person(const char* name, int age):name(name),age(age){} 8 bool operator<(const Person& b); 9 10 }; 11 bool Person::operator<(const Person& b) 12 {

第六周项目4-成员函数、友元函数和一般函数有区别

(1)阅读下面的程序,体会注释中的说明. //例:使用成员函数.友元函数和一般函数的区别 #include <iostream> using namespace std; class Time { public: Time(int h,int m,int s):hour(h),minute(m),sec(s) {} void display1(); //display1是成员函数 friend void display2(Time &); //display2是友元函数 int get

第六周项目四-成员函数、友元函数和一般函数的区别

(1)阅读下面的程序,体会注释中的说明. //例:使用成员函数.友元函数和一般函数的区别 #include <iostream> using namespace std; class Time { public: Time(int h,int m,int s):hour(h),minute(m),sec(s) {} void display1(); //display1是成员函数 friend void display2(Time &); //display2是友元函数 int get

编写高质量代码——运算符重载,是成员函数还是友元函数

一.运算符重载的四项基本原则: ▍不可臆造运算符. ▍运算符原有操作数的个数.优先级和结合性不能改变. ▍操作数中至少一个是自定义类型. ▍保持运算符的自然含义. ============================== 二.运算符重载的两种形式: ▍成员函数形式(隐含一个参数 this 指针): 1)双目运算符:参数一个 2)单目运算符:不能显示的声明参数 ▍友元函数形式(不存在隐含的参数 this 指针) 1)双目运算符:两个参数 2)单目运算符:一个参数 ===============

条款十九: 分清成员函数,非成员函数和友元函数

成员函数和非成员函数最大的区别在于成员函数可以是虚拟的而非成员函数不行.所以,如果有个函数必须进行动态绑定(见条款38),就要采用虚拟函数,而虚拟函数必定是某个类的成员函数.如果函数不必是虚拟的,情况就稍微复杂一点. 看下面表示有理数的一个类: class rational { public: rational(int numerator = 0, int denominator = 1); int numerator() const; int denominator() const; cons

const成员函数,内联函数,友元函数,static成员

原文链接:https://blog.csdn.net/qq_38646470/article/details/79795538专栏链接:https://blog.csdn.net/column/details/20026.html[TOC]#1.const成员函数const修饰成员函数在成员函数后面加const,const修饰this指针所指向的对象,也就是保证调用这个const成员函数的对象在函数内不会被改变. class Date { public : void Display () { c