【问题标题】:OOP: class without static members or complete redesignOOP:没有静态成员或完全重新设计的类
【发布时间】:2016-04-24 22:20:19
【问题描述】:

我正在教授一门 c++ 课程,在其中一个项目中,要求学生编写机器人类的代码。

Robot 构造函数是固定的,实例是从学生无法修改的函数创建的。但是,课程设计的其余部分留作练习。

我想确保机器人实例不能轻易地在彼此之间共享信息。如果学生想要共享信息,他可以创建类的静态成员或在类的实现中使用静态变量来存储有关每个实例的信息。 可能还有其他方法可以利用该语言“作弊”(例如写入文件、使用套接字……)。

有没有办法检查这种滥用(例如静态成员的存在)?在这一点上,我愿意接受任何建议。 我是否应该考虑完全重新设计,以便每个实例“生活在一个完全不同的世界中”,从而阻止它们相互通信? 这是一个根本不可能预防的问题吗?我是否应该警告他们这种行为的严重影响?

谢谢。

编辑: 我问这个问题的原因不是为了减轻评分。我计划创建一个自动化平台,学生可以在其中提交代码并让他们相互竞争。在这种情况下,我将无法在发布代码之前阅读和验证代码。 我想防止“容易”的滥用(例如静态成员),并认为更多涉及的滥用不会那么普遍。

因此我的问题真的是:有没有办法以编程方式阻止学生拥有静态成员(模板黑客或其他东西),或者我应该重新设计课程。谢谢

【问题讨论】:

  • grep static code.cpp
  • 是的,我已经想到了这个:)
  • 对类成员的访问控制在类级别,而不是单个对象。由于您正在教授这门课程,因此只需声明如果学生使用非静态成员以外的任何东西在Robot 的实例之间进行通信,他们将被打分。当然,这需要您检查代码,而不是简单地自动检查代码。
  • 还有其他方法可以在没有静态成员的情况下共享数据。如果你在代码中找到std::shared_ptr, or a common base class,你也会降级吗?
  • 是的,公共基础是另一种不被容忍的信息共享方式。我不确定如何使用 shared_ptr 来实现这一点?除非与一些静态变量结合使用,否则每个实例都不会知道其他实例。能详细点吗?

标签: c++ oop


【解决方案1】:

有没有办法检查这种滥用(例如静态成员的存在)?

是的:阅读代码。

可能有一些方法可以通过语言破解和/或在结果代码上运行解析器来自动禁止这种情况。但总的来说,如果这些解决方案能够正常工作,它们将方式矫枉过正。

所以只需做我们在行业中所做的事情:用你的眼睛检查代码,并做出相应的标记!希望您在决定给学生打分之前已经阅读了代码,所以这不应该是您的牙齿。

记得提前告诉你的学生,你不想看到这样的骇客。

【讨论】:

  • 我更新了问题!我的目标不是简化评分,而是真正防止最简单的滥用情况。
  • @elvadrias:我的回答成立。只需阅读代码。我不会假装我 100% 确定没有办法自动执行您提出的建议,但是我知道这将是 (a) 可怕的,并且 (b)不值得。我很欣赏你正在努力实现的目标,但老实说,你真的必须让人类的认知能力来解决这样的任何问题。
  • 是的,我同意自动详尽地检查每种滥用行为可能是矫枉过正。然而,一些给定的建议非常简单,可能足以阻止聪明人。无论如何,评分时会检查代码,但在线提交时不会检查代码,我不希望项目成为巨魔巨星;)
【解决方案2】:

有没有办法检查这种滥用(例如静态成员的存在)?

有点。在 C++ 中以编程方式,不 - C++ 没有反射,因此无法编写类型特征 has_static_member<T>

您基本上需要的是您自己的 C++ 解析器来生成一个 AST,然后您可以通过它来确定是否存在 static 成员。我不建议尝试编写自己的 C++ AST 解析器。幸运的是,您可以使用clang's。也可以使用in Python。现在只需弄清楚如何使用它来为您提供所需的答案。

举个例子,

class Robot {
public:
    Robot();
    void foo();
private:
    static int bar;
    double quux;
};

当运行ast-dump 命令给我:

|-CXXRecordDecl 0x491c9d8 <main.cpp:1:5, line:8:5> line:1:11 class Robot definition
| |-CXXRecordDecl 0x491caf0 <col:5, col:11> col:11 implicit referenced class Robot
| |-AccessSpecDecl 0x491cb80 <line:2:5, col:11> col:5 public
| |-CXXConstructorDecl 0x491cc50 <line:3:9, col:15> col:9 Robot 'void (void)'
| |-CXXMethodDecl 0x496f900 <line:4:9, col:18> col:14 foo 'void (void)'
| |-AccessSpecDecl 0x496f9a8 <line:5:5, col:12> col:5 private
| |-VarDecl 0x496f9e0 <line:6:9, col:20> col:20 bar 'int' static
| `-FieldDecl 0x496fa50 <line:7:9, col:16> col:16 quux 'double'

所以您正在寻找属于类成员的VarDecls(因为非静态成员是FieldDecls)。

【讨论】:

  • 谢谢,这是一种非常简单的方法,我可以将其包含在预处理脚本中。这似乎比简单的 grep static 更健壮。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-18
  • 1970-01-01
  • 2015-01-26
  • 1970-01-01
  • 2014-09-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多