c++ - 如何在 Header 文件中实现模板?
问题描述
我得到的错误是
(base) ethanordaz@Ethans-MBP Fraction % g++ main.cpp fractionClass.cpp
Undefined symbols for architecture x86_64:
"fraction::Fraction fraction::Fraction::operator*<fraction::Fraction>(fraction::Fraction)", referenced from:
_main in main-8169dc.o
"fraction::Fraction fraction::Fraction::operator+<int>(int)", referenced from:
_main in main-8169dc.o
ld: symbol(s) not found for architecture x86_64
主文件
#include <iostream>
#include <cmath>
#include <string>
#include "fractionClass.h"
int main()
{
fraction::Fraction myFrac2(2,3);
fraction::Fraction newFrac = myFrac2 + 1;
myFrac2 = newFrac*myFrac2;
std::cin >> myFrac2;
std::cout << myFrac2 << std::endl;
std::cout << newFrac << std::endl;
return 0;
}
分数类.cpp
#include <iostream>
#include <cmath>
#include <string>
#include "fractionClass.h"
namespace fraction {
Fraction::Fraction(int x, int y) {
numerator = x;
denominator = y;
simplify();
}
template <typename Number>
Fraction::Fraction(Number x) {
int xint = (int)x;
int zeros = 0;
if (xint-x != 0){
std::string tempString = std::to_string(x-xint);
zeros = tempString.size();
}
numerator = x * std::pow(10,zeros);
denominator = std::pow(10,zeros);
simplify();
}
Fraction::Fraction(){
}
double Fraction::getDecimal() {
double decimal = (double)numerator/(double)denominator;
return decimal;
}
template <typename Number>
void Fraction::multiply(Number x) {
int xint = (int)x;
int zeros = 0;
if (xint-x != 0){
std::string tempString = std::to_string(x-xint);
zeros = tempString.size();
}
numerator = numerator * x;
denominator = denominator * std::pow(10,zeros);
simplify();
}
void Fraction::multiply(Fraction x) {
numerator = numerator * x.numerator;
denominator = denominator * x.denominator;
simplify();
}
template <typename Number>
void Fraction::divide(Number x) {
int xint = (int)x;
int zeros = 0;
if (xint-x != 0){
std::string tempString = std::to_string(x-xint);
zeros = tempString.size();
}
numerator = numerator * std::pow(10,zeros);
denominator = denominator * x;
simplify();
}
void Fraction::divide(Fraction x) {
numerator = numerator * x.denominator;
denominator = denominator * x.numerator;
simplify();
}
void Fraction::simplify() {
int a = numerator;
int b = denominator;
int greatestCommonDivisor;
int greatestNumber = a>b ? a : b;
while (a%10==0 && b%10==0) {
a = a/10;
b = b/10;
}
while (a%2==0 && b%2==0) {
a = a/2;
b = b/2;
}
do {
while (true) {
if (a%greatestNumber==0 && b%greatestNumber==0) {
greatestCommonDivisor = greatestNumber;
break;
} else {
greatestNumber--;
}
if (greatestNumber <= 0) {
greatestCommonDivisor = 1;
break;
}
}
a = a/greatestCommonDivisor;
b = b/greatestCommonDivisor;
} while (greatestCommonDivisor != 1);
numerator = a;
denominator = b;
}
template <typename Number>
void Fraction::add(Number x) {
int xint = (int)x;
int zeros = 0;
if (xint-x != 0){
std::string tempString = std::to_string(x-xint);
zeros = tempString.size();
}
x = x*denominator;
Number xdenom = std::pow(10,zeros) * denominator;
numerator = numerator * (xdenom/denominator);
denominator = denominator * (xdenom/denominator);
numerator = numerator + x;
simplify();
}
template <typename Number>
void Fraction::sub(Number x) {
int xint = (int)x;
int zeros = 0;
if (xint-x != 0){
std::string tempString = std::to_string(x-xint);
zeros = tempString.size();
}
x = x*denominator;
Number xdenom = std::pow(10,zeros) * denominator;
numerator = numerator * (xdenom/denominator);
denominator = denominator * (xdenom/denominator);
numerator = numerator - x;
simplify();
}
void Fraction::add(Fraction x) {
x.numerator = x.numerator*denominator;
int xdenom = x.denominator * denominator;
numerator = numerator * (xdenom/denominator);
denominator = denominator * (xdenom/denominator);
numerator = numerator + x.numerator;
simplify();
}
void Fraction::sub(Fraction x) {
x.numerator = x.numerator*denominator;
int xdenom = x.denominator * denominator;
numerator = numerator * (xdenom/denominator);
denominator = denominator * (xdenom/denominator);
numerator = numerator - x.numerator;
simplify();
}
std::string Fraction::display() {
simplify();
std::string output = std::to_string(numerator);
output += '/';
output += std::to_string(denominator);
return output;
}
template <typename Number>
Fraction Fraction::operator + (Number pos) {
Fraction toReturn(numerator,denominator);
toReturn.add(pos);
return toReturn;
}
template <typename Number>
Fraction Fraction::operator - (Number pos) {
Fraction toReturn(numerator,denominator);
toReturn.sub(pos);
return toReturn;
}
template <typename Number>
Fraction Fraction::operator / (Number pos) {
Fraction toReturn(numerator,denominator);
toReturn.divide(pos);
return toReturn;
}
template <typename Number>
Fraction Fraction::operator * (Number pos) {
Fraction toReturn(numerator,denominator);
toReturn.multiply(pos);
return toReturn;
}
std::ostream& operator<<(std::ostream& os, const Fraction& frac);
std::istream& operator>>(std::istream& is, Fraction& frac);
std::ostream& operator<<(std::ostream& os, const Fraction& frac) {
os << frac.numerator << "/" << frac.denominator;
return os;
}
std::istream& operator>>(std::istream& is, Fraction& frac) {
is>> frac.numerator >> frac.denominator;
return is;
}
}
fractionClass.h 是
#include <iostream>
#include <cmath>
#include <string>
#include <algorithm>
#ifndef FRACTION_H
#define FRACTION_H
namespace fraction {
class Fraction {
private:
int numerator;
int denominator;
public:
Fraction(int x, int y);
template <typename Number>
Fraction(Number x);
Fraction();
double getDecimal();
template <typename Number>
void multiply(Number x);
void multiply(Fraction x);
template <typename Number>
void divide(Number x);
void divide(Fraction x);
void simplify();
template <typename Number>
void add(Number x);
template <typename Number>
void sub(Number x);
void add(Fraction x);
void sub(Fraction x);
std::string display();
template <typename Number>
Fraction operator + (Number pos);
template <typename Number>
Fraction operator - (Number pos);
template <typename Number>
Fraction operator / (Number pos);
template <typename Number>
Fraction operator * (Number pos);
friend std::ostream& operator<<(std::ostream& os, const Fraction& frac);
friend std::istream& operator>>(std::istream& is, Fraction& frac);
};
std::ostream& operator<<(std::ostream& os, const Fraction& frac);
std::istream& operator>>(std::istream& is, Fraction& frac);
}
#endif
这是我第一次弄乱头文件,这段代码在同一个空间运行时会编译。我在 macOS 中工作,但如果它解决了问题,我可以使用 windows。这段代码是一种分数类,它仍在制作中,但它变得太大了,所以我想使用多个文件。你能告诉我一个你将如何解决这个问题的例子吗?这将不胜感激。谢谢你。问题是有人告诉我模板必须在头文件中实现,所以我尝试过,但是我无法使用它们,有人可以告诉我如何在这里实现模板的示例。顺便说一句,我知道模板是问题所在,因为我删除了它们并且效果很好,但是我不想为每种数据类型编写每个函数。
解决方案
推荐阅读
- android - ROOM 如何在列表中为拖放交换两个实体
- java - 如何提供访问权限(Spring Security)
- r - 如何在 Shiny 中使用 inputSlider 和 top_n
- python - 列表如何在 python 中实现异构?
- python - 有没有办法进一步减少这个python代码中的“for循环”?
- php - 为什么即使直接访问也无法加载徽标?
- c# - 如何使用 Octokit 上传 Zip 文件?
- php - 在 laravel 中获取奇怪的 ip 62cf6cb1-c205-4a36-9c5d-be2e1524ea29.local
- c - 无法包含 C 编译的文件夹
- java - 我们如何使用 ElasticSearch 按 q 优先搜索 - 全文搜索