@Alyona_pr

Как правильно реализовать шаблонный класс рациональных чисел в С++?

Добрый день, задача: написать шаблонный класс рациональных чисел с перегрузкой сокращения дроби.
Для варианта, когда числитель и знаменатель изначально везде типа int, всё работает.
Проблема в том, чтоб сделать этот класс именно шаблонным.
Сейчас выводит такие ошибки:
error LNK2019: ссылка на неразрешенный внешний символ "class std::basic_istream<char,struct std::char_traits<char> > & __cdecl operator>>(class std::basic_istream<char,struct std::char_traits<char> > &,class rat<int> &)" (??5@YAAAV?$basic_istream@DU?$char_traits@D@std@@@std@@AAV01@AAV?$rat@H@@@Z) в функции _main
error LNK2019: ссылка на неразрешенный внешний символ "class std::basic_ostream<char,struct std::char_traits<char> > & __cdecl operator<<(class std::basic_ostream<char,struct std::char_traits<char> > &,class rat<int> const &)" (??6@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@std@@AAV01@ABV?$rat@H@@@Z) в функции _main
 fatal error LNK1120: неразрешенных внешних элементов: 2


Код написан в Visual Studio:
#include <iostream>
using namespace std;

template <class T> 
class rat{
	T ch, zn;
public:
	friend istream& operator>>(istream& stream_in, rat<T> &rvalue); 
	friend ostream& operator<<(ostream& stream_out,const rat<T> &rvalue); 
	T nod(T, T);  // наибольший общий делитель 
	T abs(T); // модуль числа 
	rat(int = 0, int = 1); 
	void norm(); // для сокращения дроби  
};

template <class T> T rat <T>::abs(T x) {
	if (x < 0)
		return (-1)*x;
	return x;
}
template <class T> T rat <T>::nod(T x, T y) { 
	if (x == 0 || y == 0)
		return 1;
	while (x != y)
		if (x > y)
			x = x - y;
		else
			y = y - x;
	return x;
}
template <class T> rat <T>::rat(int x, int y) { 
	if (!y || !x) {
		ch = 0;
		zn = 1;
	}
	ch = x;
	zn = y;
	this->norm();
}
template <class T> void rat <T>::norm() {  
	int sign = 1;
	if (ch*zn < 0)
		sign = (-1);
	ch = abs(ch);
	zn = abs(zn);
	T b = nod(ch, zn);
	if (ch == 0 || zn == 0)
		zn = 1; 
	if (b == 1)
		return;
	ch = (ch / b)*sign;
	zn = zn / b;
}

template <class T> istream& operator>>(istream& stream_in, rat<T> &rvalue) {
	cout << "Enter rational value (a/b): ";
	stream_in >> rvalue.ch;
	stream_in.ignore();
	stream_in >> rvalue.zn;
	cout << endl;
	return stream_in;
};

template <class T> ostream& operator<<(ostream& stream_out,const rat<T> &rvalue) {
	stream_out << "Rational number: " << rvalue.ch << "/" << rvalue.zn << endl;
	return stream_out;
}

int main() {
	rat <int> a;
	cin >> a;  
	cout <<  a  << endl;

	return 0;
}
  • Вопрос задан
  • 401 просмотр
Решения вопроса 1
@User700
Здесь:
template <class T> istream& operator>>(istream& stream_in, rat<T> &rvalue) {
  cout << "Enter rational value (a/b): ";
  stream_in >> rvalue.ch;
  stream_in.ignore();
  stream_in >> rvalue.zn;
  cout << endl;
  return stream_in;
};

Не должно быть привязки к cout. Работа только с потоком stream_in, т.к. данные не обзательно считываются с консоли, а такой оператор должен предполагать и считывание из файла. Приглашение ко вводу нужно делать "в main", или реализовать метод для ввода с приглашением, принимающий два потока. Перевод строки также после ввода не нужно делать.
Основная проблема:
Не совсем правильное решение, см. комментарии:
public:
  template <class T1> 
  friend istream& operator>>(istream& stream_in, rat<T1> &rvalue); 
  template <class T1>
  friend ostream& operator<<(ostream& stream_out, const rat<T1> &rvalue);

UPD:
Правильное
template <class T> class rat;
template <class T> istream& operator>>(istream& stream_in, rat<T> &rvalue);
template <class T> ostream& operator<<(ostream& stream_out,const rat<T> &rvalue);

template <class T> 
class rat{
  T ch, zn;
public:
  friend istream& operator>> <T> (istream& stream_in, rat &rvalue); 
  friend ostream& operator<< <T> (ostream& stream_out, const rat &rvalue);
  //......
};
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы