OJ中使用类的一些事项(单一cpp)

Background:博主是一名大一学生,如今下学期新增一门课程:面向对象程序设计(C++),在此接触了类及其的应用。本文意图是讲解类在OJ平台上的正确运用。

添加类

这里只讲我自己接触的两个编译器:VC6.0、Visual Studio 2019。

VC

可通过右击项目名称并选择new class来系统地添加类,此举会系统规范地创建一个新的类,生成相关的头文件及源码(cpp文件),生成后便可以对其进行编辑、引用。这种做法将类运用得很有仪式感,也是常规的一种操作。
在这里插入图片描述
可,OJ是不允许我们这样做的,它只有一个面板使我们递交代码,(花里胡哨的)独立的类头文件及源码是无法递交的,所以我们创建程序的时候得选择“一个空工程”(见下图)。
在这里插入图片描述
然后便可以在开头添上#include<stdio.h>可供OJ评测,我们就在这个空白面板中进行代码编写。这种情况下我们不能用上面的方法进行类的添加。而是单独进行类的代码填塞。下以时间类为例,这段代码就是在开头直接定义Time类。在这里还有一点需注意,类的数据默认为private不可从外部访问(也是特点),在OJ中为了便于操作我习惯在最前面加上public。

#include <iostream>
using namespace std;
class Time
{
public:
    int h, m, s;
    void add();
};
void Time::add()
{
    s++;
    if (s >= 60)
    {
        m++;
        s = 0;
    }
    if (m >= 60)
    {
        h++;
        m = 0;
    }
    if (h >= 24)
        h = 0;
}
int main()
{
    int i, n;
    Time x;
    cin >> x.h >> x.m >> x.s >> n;
    for (i = 0; i < n; i++)
        x.add();
    cout << x.h << " " << x.m << " " << x.s << endl;
    return 0;
}

Visual Studio

基础类的定义与VC类似,同样是右击项目名进行类的添加,会生成.h和.cpp文件。
在这里插入图片描述
一样的,在OJ中,不能这样添加类,还是得在单个的cpp文件中添加,同上一段代码,在开头进行类的定义。

多个类

嵌套

在这,我把存在多个类(>=2)但彼此不互相关联的情况称作类的嵌套,如下段代码
这段代码含有两个类,复数类和复数数组类,显然,复数数组类包含复数类,我将这种情况称为“嵌套”,是因为它含有一种“元类”,即一个基础成员类(如复数类),它内部不再包含其他任何类,同时它也是别的复杂类的一种组成成分。

class Complex
{
public:
    int real, imag;
};
class ComplexArray
{
public:
    int n;
    Complex a[105];
}

遇到这种情况,只需要像叠罗汉一样,按类从简单到复杂、被包含到包含从上至下书写即可。

关联

可遇到所有需要的类都彼此之间有关(包含)的情况呢?
下面给出一例(省略部分函数代码区块)

class Matrix3
{
public:
    int v[3][3];
    Vector3 operator*(Vector3 b);
};
class Vector3
{
public:
    int x, y, z;
    Vector3 operator*(Matrix3& c);
};

这段代码中,Matrix3类的重载函数包含Vector3类,Vector3类的重载函数也包含Matrix3类,似乎找不到那个“元类”的存在,含有该段代码的程序递交肯定是会有编译错误的,因为在最前的Matrix3类前没有定义Vector3类,标识符无效。
这看似是个死循环,存在矛盾,可在一个cpp文件中如何解决这个问题呢?博主开始也被这个问题困住了,后来去询问了下老师,回答为四个字:
“前向说明”
类的说明和类的定义,分开写,下面放完整代码

class Vector3;
class Matrix3
{
public:
    int v[3][3];
    void set();
    void Output();
    Matrix3 operator*(Matrix3 b);
    Vector3 operator*(Vector3 b);
    Matrix3 operator*(int x);
    Matrix3 operator+(Matrix3 b);
    Matrix3 operator-(Matrix3 b);
};

class Vector3
{
public:
    int x, y, z;
    void set()
    {
        cin >> x >> y >> z;
    }
    void Output()
    {
        cout << x << " " << y << " " << z << endl;
    }
    Vector3 operator+(Vector3 b)
    {
        Vector3 d;
        d.x = x + b.x;
        d.y = y + b.y;
        d.z = z + b.z;
        return d;
    }
    Vector3 operator-(Vector3 b)
    {
        Vector3 d;
        d.x = x - b.x;
        d.y = y - b.y;
        d.z = z - b.z;
        return d;
    }
    Vector3 operator*(int m)
    {
        Vector3 d;
        d.x = x * m;
        d.y = y * m;
        d.z = z * m;
        return d;
    }
    Vector3 operator*(Vector3 b)
    {
        Vector3 d;
        d.x = y * b.z - z * b.y;
        d.y = z * b.x - x * b.z;
        d.z = x * b.y - y * b.x;
        return d;
    }
    Vector3 operator*(Matrix3& c)
    {
        Vector3 a;
        a.x = x * c.v[0][0] + y * c.v[1][0] + z * c.v[2][0];
        a.y = x * c.v[0][1] + y * c.v[1][1] + z * c.v[2][1];
        a.z = x * c.v[0][2] + y * c.v[1][2] + z * c.v[2][2];
        return a;
    }
};
void Matrix3::set()
{
    for (int i = 0; i < 3; i++)
        for (int j = 0; j < 3; j++)
            cin >> v[i][j];
}
void Matrix3::Output()
{
    for (int i = 0; i < 3; i++)
        for (int j = 0; j < 3; j++)
            cout << v[i][j] << " ";
    cout << endl;
}
Matrix3 Matrix3::operator*(Matrix3 b)
{
    Matrix3 a;
    for (int i = 0; i < 3; i++)
        for (int j = 0; j < 3; j++)
            a.v[i][j] = v[i][0] * b.v[0][j] + v[i][1] * b.v[1][j] + v[i][2] * b.v[2][j];
    return a;
}
Vector3 Matrix3::operator*(Vector3 b)
{
    Vector3 a;
    a.x = v[0][0] * b.x + v[0][1] * b.y + v[0][2] * b.z;
    a.y = v[1][0] * b.x + v[1][1] * b.y + v[1][2] * b.z;
    a.z = v[2][0] * b.x + v[2][1] * b.y + v[2][2] * b.z;
    return a;
}
Matrix3 Matrix3::operator*(int x)
{
    Matrix3 a;
    for (int i = 0; i < 3; i++)
        for (int j = 0; j < 3; j++)
            a.v[i][j] = v[i][j] * x;
    return a;
}
Matrix3 Matrix3::operator+(Matrix3 b)
{
    Matrix3 a;
    for (int i = 0; i < 3; i++)
        for (int j = 0; j < 3; j++)
            a.v[i][j] = v[i][j] + b.v[i][j];
    return a;
}
Matrix3 Matrix3::operator-(Matrix3 b)
{
    Matrix3 a;
    for (int i = 0; i < 3; i++)
        for (int j = 0; j < 3; j++)
            a.v[i][j] = v[i][j] - b.v[i][j];
    return a;
}

我把这种写法称为“汉堡包写法”,开始先在开头放置“class Vector3;”作为一个“微申明”(光秃秃),然后再对Matrix3类进行一个“具体申明”(含具体数据成员、函数),接下来便可以在Vector3类内进行完整函数书写。对Matrix3类的成员函数,选择在最后进行外部“补写”。
为什么?因为它的重载函数内包含对Vector3数据成员的使用,而此时Vector3只是个定义在开头的空壳而已,啥也没有,必然会CE。

END

其实类在OJ中的应用相对来说并没有那么广,主要还是需要一些数据结构及算法的掌握,但同时也希望本文能帮到一些人!

Lrice处女作

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值