【大一程序设计基础作业】定义:类模板T_Counter,实现基本数据类型的+、-、*、=、>>、<<运算;类模板T_Counter 实现向量运算。

写这篇博文的时候我真的真的真的了百感交集

事情是这样的,这份作业我写了不下6个小时,就是因为各种细节的错误,各种bug层出不穷,一个bug修完又出现新的bug,一次次的崩溃,最终还是磨出来了……

来看题:定义:类模板T_Counter,实现基本数据类型的+、-、*、=、>>、<<运算;类模板T_Counter 实现向量运算。

读题一开始觉得这道题人畜无害,写个模板就完事了,但实际编程过程中问题是真的不少。

首先定义类模板T_Counter

template<typename T>
class T_Counter
{
private:T a;
public:
    void Print() { cout << a << endl; }
    T_Counter() {}
    T_Counter(T x) { a = x; }
};

就是上面这个样子,这个时候苯人还没有意识到问题的严重性。就是很简单的一个模板类,顺手写个构造函数和print函数。

之后就是实现基本数据类型的+-*/<<>>运算,这边我就遇到了第一个细节:在每个友元函数的声明之前,都要写上模板,而不能直接使用类模板中的数据类型。

    template<typename T>
    friend T_Counter<T> operator+(const T_Counter<T>& tc1, const T_Counter<T>& tc2);
    template<typename T>
    friend T_Counter<T> operator-(const T_Counter<T>& tc1, const T_Counter<T>& tc2);
    template<typename T>
    friend T_Counter<T> operator*(const T_Counter<T>& tc1, const T_Counter<T>& tc2);
    template<typename T>
    friend T_Counter<T> operator/(const T_Counter<T>& tc1, const T_Counter<T>& tc2);
    template<typename T>
    friend T_Counter<T> operator<<(const T_Counter<T>& tc1, const T_Counter<T>& tc2);
    template<typename T>
    friend T_Counter<T> operator>>(const T_Counter<T>& tc1, const T_Counter<T>& tc2);
    T_Counter& operator=(T_Counter tc)
    {
        this->a = tc.a;
        return *this;
    }

当然这个bug没有卡我很久,报错之后就马上注意到了(忘了截图了,不然说实话20多个报错还是挺壮观的)写完之后就是上面这个样子(函数体的写法我就略过了,反正后面有完整代码的)写到这里还是有惊无险。我当时甚至在想这道题有没有写的必要,看起来只要把以上内容copy一遍再稍作修改就能结束了

template<typename T>
class T_Vector {
private:
    T* p;
    int size;
public:
   
    T_Vector& operator=(const T_Vector& tc)
    {
        
        this->size = tc.size;
        this->p=tc.p;
        return *this;
    }
    void Print()
    {
        for (int i = 0; i < size; i++)
            cout << p[i];
    }
    T_Vector(int n) {
        size = n;
        p = new T[size];
    }
    T_Vector(int s, T* pp) {
        size = s;
        p = pp;
    }
    ~T_Vector() {
        delete[] p;  size = 0;
    }

    T& operator[](int i);
    template<typename U>friend T_Vector<U> operator+(const T_Vector<U>& tc1, const T_Vector<U>& tc2);
   

 几乎都是直接照搬上面的T_Counter的代码,上面的能跑理论上这边也能跑。但

 

现实就是给我弹了个这个,特别眼熟的框,我之前一定遇到过一样的问题……

 于是我就在这边改了很久。设断点、删改代码,初步排查是+的重载出了问题。我当时以为单纯是我函数体或者函数声明有问题,于是就一遍遍地改。翻书、查csdn,甚至问chatgpt。一开始是对着别人的代码修改,但是修改了好几个版本都没有解决问题。后来甚至干脆复制别人的函数,也是编译出问题。在当时的我眼中这就是个很玄学的问题了,因为别人的代码全篇能跑,但别人的函数单拿过来给我跑不了(其实这个时候就应该意识到不是这个重载运算符出问题了,但是由于删掉这一部分能完美地跑出结果,所以当时的我就一直纠结在这个地方)在这个地方几乎花了我写这个程序的90%时间……

最后我实在解决不了,想着先把这个弹窗弄明白吧,于是就直接查了下这个弹窗:

https://blog.csdn.net/qq_59278530/article/details/127163331

查到了上面这个东东,总结来说就是在调用函数的时候没有没有使用引用作为参数,导致类在实例化后重复析构的问题。为了确认我是否也遇到了这个问题,我直接删掉了我的析构函数,果不其然,跑通了。

现在定位到是析构函数出了问题,但是我仔细检查了一遍,由于我良好的编程习惯,我的参数全都是const&,很规范的用法。问题到这边似乎又进入了死胡同……毕竟是析构函数出了问题,这种小型的程序,析构函数的存在意义其实没有特别大,所以一开始的我选择直接删掉析构函数

 本来已经打算摆烂交作业了,但是我的脑海中突然闪过一个画面,那是之前一次写博文,我清楚地记得我在博文中强调了Vector类动态数组地拷贝构造函数需要进行特殊的处理……

https://blog.csdn.net/2301_77136128/article/details/129900174?spm=1001.2014.3001.5502

↑↑于是我参考了……我自己之前写的博文……

(坏了,那还是我第一次写详解) 

原来出问题的是拷贝构造函数

T_Vector(const T_Vector& t)
    {
        this->size = t.size;
        this->p = t.p;
        this->p = new T[t.size];
        for (int i = 0; i < t.size; i++)
            this->p[i] = t.p[i];
    }

按照之前博文说的方法改完,豁然开朗

难怪记得这个报错弹窗十分眼熟,原来我在那个时候就已经遇到了这个问题……

以下就是完整代码了;但我还要再啰嗦几句:由于>><<已经重载,cin,cout在不对类的实例上进行操作时有概率报错,于是我也是使用简单粗暴的方法:把报错的cin,cout改为printf、scanf,用c解决c++问题(doge)

具体printf和scanf的用法自行csdn(苯人也不太熟,只是碰巧会用一点)


#include<iostream>
using namespace std;
template<typename T>
class T_Counter
{
private:T a;
public:
    void Print() { cout << a << endl; }
    template<typename T>
    friend T_Counter<T> operator+(const T_Counter<T>& tc1, const T_Counter<T>& tc2);
    template<typename T>
    friend T_Counter<T> operator-(const T_Counter<T>& tc1, const T_Counter<T>& tc2);
    template<typename T>
    friend T_Counter<T> operator*(const T_Counter<T>& tc1, const T_Counter<T>& tc2);
    template<typename T>
    friend T_Counter<T> operator/(const T_Counter<T>& tc1, const T_Counter<T>& tc2);
    template<typename T>
    friend T_Counter<T> operator<<(const T_Counter<T>& tc1, const T_Counter<T>& tc2);
    template<typename T>
    friend T_Counter<T> operator>>(const T_Counter<T>& tc1, const T_Counter<T>& tc2);
    T_Counter& operator=(T_Counter tc)
    {
        this->a = tc.a;
        return *this;
    }
    T_Counter() {}
    T_Counter(T x) { a = x; }
};

template<typename T>
T_Counter<T>operator+(const T_Counter<T>& tc1, const T_Counter<T>& tc2)
{
    T r = tc1.a + tc2.a;
    return T_Counter<T>(r);
}
template<typename T>
T_Counter<T>operator-(const T_Counter<T>& tc1, const T_Counter<T>& tc2)
{
    T r = tc1.a - tc2.a;
    return T_Counter<T>(r);
}
template<typename T>
T_Counter<T>operator*(const T_Counter<T>& tc1, const T_Counter<T>& tc2)
{
    T r = tc1.a * tc2.a;
    return T_Counter<T>(r);
}
template<typename T>
T_Counter<T>operator/(const T_Counter<T>& tc1, const T_Counter<T>& tc2)
{
    T r = tc1.a / tc2.a;
    return T_Counter<T>(r);
}
template<typename T>
T_Counter<T>operator>>(const T_Counter<T>& tc1, const  T_Counter<T>& tc2)
{
    T r = tc1.a >> tc2.a;
    return T_Counter<T>(r);
}
template<typename T>
T_Counter<T>operator<<(const T_Counter<T>& tc1, const T_Counter<T>& tc2)
{
    T r = tc1.a << tc2.a;
    return T_Counter<T>(r);
}
template<typename T>
class T_Vector {
private:
    T* p;
    int size;
public:
    T_Vector(const T_Vector& t)
    {
        this->size = t.size;
        this->p = t.p;
        this->p = new T[t.size];
        for (int i = 0; i < t.size; i++)
            this->p[i] = t.p[i];
    }
    T_Vector& operator=(const T_Vector& tc)
    {
        delete[]p;
        this->size = tc.size;
        p = new T[size];
        for (int i = 0; i < size; i++)
            p[i] = tc.p[i];
        return *this;
    }
    void Print()
    {
        for (int i = 0; i < size; i++)
            cout << p[i];
    }
    T_Vector(int n) {
        size = n;
        p = new T[size];
    }
    T_Vector(int s, T* pp) {
        size = s;
        p = pp;
    }
    ~T_Vector() {
        delete[] p;  size = 0;
    }

    T& operator[](int i);
    template<typename U>friend T_Vector<U> operator+(const T_Vector<U>& tc1, const T_Vector<U>& tc2);
    template<typename U>friend T_Vector<U> operator-(const T_Vector<U>& tc1, const T_Vector<U>& tc2);
    template<typename U>friend T_Vector<U> operator*(const T_Vector<U>& tc1, const T_Vector<U>& tc2);
    template<typename U>friend T_Vector<U> operator/(const T_Vector<U>& tc1, const T_Vector<U>& tc2);
    template<class T_Vector>friend ostream& operator<<(ostream& out, const T_Vector& p);
    template<class T_Vector>friend istream& operator>>(istream& in, const T_Vector& p);
};

template <typename T>
T& T_Vector<T>::operator[](int i) {
    if (i < 0 || i >= size) {
        printf("error\n");
        exit(0);
    }
    return p[i];
}
template<class T_Vector>
ostream& operator<<(ostream& out, const T_Vector& p)
{
    for (int i = 0; i < p.size; i++)
    {
        cout << p.p[i];
        printf(" ");
    }
    cout << endl;
    return out;
}
template<class T_Vector>
istream& operator>>(istream& in, const T_Vector& p)
{
    printf("请输入数据\n");
    for (int i = 0; i < p.size; i++)
    {
        cin >> p.p[i];
    }
    return in;
}
template<class U>
T_Vector<U>operator+(const T_Vector<U>& tc1, const T_Vector<U>& tc2)
{
    int s = tc1.size;
    U* p;
    p = new U[s];
    T_Vector<U> tmp(s, p);
    for (int i = 0; i < s; i++)
    {
        p[i] = tc1.p[i] + tc2.p[i];
    }
    return tmp;
}
template<typename U>
T_Vector<U>operator-(const T_Vector<U>& tc1, const T_Vector<U>& tc2)
{
    int s = tc1.size;
    U* p;
    p = new U[s];
    T_Vector<U> tmp(s, p);
    for (int i = 0; i < s; i++)
    {
        p[i] = tc1.p[i] - tc2.p[i];
    }
    return tmp;
}
template<typename U>
T_Vector<U>operator*(const T_Vector<U>& tc1, const T_Vector<U>& tc2)
{
    int s = tc1.size;
    U* p;
    p = new U[s];
    T_Vector<U> tmp(s, p);
    for (int i = 0; i < s; i++)
    {
        p[i] = tc1.p[i] * tc2.p[i];
    }
    return tmp;
}
template<typename U>
T_Vector<U>operator/(const T_Vector<U>& tc1, const T_Vector<U>& tc2)
{
    int s = tc1.size;
    U* p;
    p = new U[s];
    T_Vector<U> tmp(s, p);
    for (int i = 0; i < s; i++)
    {
        p[i] = tc1.p[i] / tc2.p[i];
    }
    return tmp;
}

int main()
{
    T_Counter<double>a(5), b(6.24);
    T_Counter<double>c = a + b;
    printf("a+b=");
    c.Print();
    c = a - b;
    printf("a-b=");
    c.Print();
    c = a * b;
    printf("a*b=");
    c.Print();
    c = a / b;
    printf("a/b=");
    c.Print();
    T_Vector<double> x(5);
    cin >> x;
    T_Vector<double>y(5);
    cin >> y;
   printf( "x+y=\n");
    cout << x + y;
    printf("x-y=\n");
    cout << x - y;
    printf("x*y=\n");
    cout << x * y;
    printf("x/y=\n");
    cout << x + y;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值