首页 > 解决方案 > 如何在 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。这段代码是一种分数类,它仍在制作中,但它变得太大了,所以我想使用多个文件。你能告诉我一个你将如何解决这个问题的例子吗?这将不胜感激。谢谢你。问题是有人告诉我模板必须在头文件中实现,所以我尝试过,但是我无法使用它们,有人可以告诉我如何在这里实现模板的示例。顺便说一句,我知道模板是问题所在,因为我删除了它们并且效果很好,但是我不想为每种数据类型编写每个函数。

标签: c++

解决方案


推荐阅读