C++14类函数错误: "Object has no attribute ' value'"

标签 c++ c++14

编辑:全面检修

我正在制作一种编程语言(类似于 Python),至少现在,我正在尝试将它编译成 C++。我遇到一个错误,其中 C++ 表示类 “Object” 中没有成员 “value”。这是一个编译错误。我理解 为什么 C++ 这样做,因为它必须在编译时知道 value 的类型,所以我要求 < em>备选方案。

它唯一会给出的是 Object 的实例子类,其中成员 "value" 将被定义,这是一个编译错误。

我不能在 Object 类中声明成员 "value",因为它的类型取决于它所在的子类。这也必须与 floats 和字符串,因此使用 Integer 实例而不是 Object 实例定义函数将不起作用。

下面是一些代码,其中包含如何使用这些对象的示例:

auto user_i = std::make_unique<Integer>(2);
  std::cout << (*user_i).equals(*std::make_unique<Float>(2.0).get()) << std::endl;

这里是重要的类定义:

  class Object {
  public:
    bool equals(Object& other) {
      throw "Not implemented!";
    }
  };
  class Integer: public Object {
  public:
    int value;
    Integer(int val) {
      value = val;
    }
    bool equals(Object& other) {
      return value == other.value;
    }
  };
class Float: public Object {
  public:
    double value;
    Float(double val) {
      value = val;
    }
    bool equals(Object& other) {
      return value == other.value;
    }
  };
class String: public Object {
  public:
    string value;
    String(string val) {
      value = val;
    }
    bool equals(Object& other) {
      return value.compare(other.value) == 0;
    }
  };

不应该是2 == "2",而是应该是2 == 2.0 == 2.000

然后是像 add 这样的方法的复杂化(我的意思是返回一个值,仍然不修改对象)。 @Michael Karcher 建议的 equals 方法可以正常工作,但是例如 2+3 应该返回 5,而不是 5.00000.

更麻烦的是,用户定义的 Object(在我的语言中是 Class)应该能够覆盖 add 等方法。

最佳答案

除了主要问题之外,您的示例还有几个问题。我从小问题着手解决它们。

  1. 您需要声明equals作为virtual在基类中。 与 Java 不同,动态分派(dispatch)不是 C++ 中的默认设置,但必须使用 virtual 按方法请求像这样的属性:
class Object {
public:
  virtual bool equals(Object other) {
    throw "Not implemented";
  }
}
  1. 您要按值 传递要与之比较的对象。 与 Java 不同,在 C++ 中甚至可以按值传递类类型。这意味着函数 equals获取 Object 的拷贝与 - 比较,只是。您要比较的对象部分,包括 value成员,不要复制到传递给 equals 的参数中.您应该通过引用 传递参数。作为您的equals函数不需要修改您比较的对象,一个没有写权限的引用(由于语法原因通常称为 const 引用)就足够了:
class Object {
public:
  virtual bool equals(const Object& other) {
    throw "Not implemented";
  }
}
  1. 如果您编写的基类仅提供需要在每个派生类中重写的函数签名,则您不会让它抛出任何东西,而是通过将其声明为纯来使其抽象virtual 函数,使用 =0句法。这可以防止您意外创建 Object无法比较的实例。这将捕获丢失的传递引用:
class Object {
public:
  virtual bool equals(const Object& other) = 0;
}

现在,让我们来回答您的问题:

这种方法适用于 JavaScript 或 Python 等动态类型语言,但不适用于 C++。 在编译过程中,编译器必须知道在哪里可以找到成员 value在对象中 other及其类型。如果你只是传入任何 Object ,编译器无法知道它。甚至 也不知道:类型可能是 intfloat .所以你和编译器都不知道你传递给比较的对象中是float值还是int值。如果Integer对象应该与 Integer 都具有可比性和 Float对象,您要么需要比较方法,要么需要一种方法来获得通用 value一种常见的类型。在这种情况下,在具有 32 位整数的机器上,每个整数值都可以在 double 中精确表示变量。您可以向 Object 添加第二个函数类名为 as_double像这样:

class Object {
public:
  virtual bool equals(const Object &other) const = 0;
  virtual double as_double() const = 0;
}

我还标记了方法const ,这意味着您可以在对象上调用它们或使用您可能不会写入的引用。现在你可以实现 IntegerFloat像这样:

class Integer: public Object {
public:
  int value;
  Integer(int val) {
    value = val;
  }
  bool equals(const Object & other) const {
    return value == other.as_double();
  }
  double as_double() const {
    return value;
  }
};
class Float: public Object {
public:
  double value;
  Float(double val) {
    value = val;
  }
  bool equals(const Object & other) const {
    return value == other.as_double();
  }
  double as_double() const {
    return value;
  }
};

而且,如果您查看 equals方法,现在这两种类型几乎相同:您将参数的值提取为 double 值,并将其与本地值进行比较(在 Integer 的情况下,本地值也被隐式转换为 double 值。所以您可以还使用在两个对象上调用 to_double 的通用比较实现,您不必费心在每个子类中实现 equals:

class Object {
public:
  bool equals(const Object& other) const {
    return as_double() == other.as_double();
  }
  virtual double as_double() const = 0;
}

请注意,这仅适用于 double实际上能够表示所有值——甚至那些存储在 Integers 中的值.如果您的实际用例没有可以转换为的通用类型,则您需要更复杂的解决方案。

关于C++14类函数错误: "Object has no attribute ' value'",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56762243/

相关文章:

c++ - 在文件中读取和存储整数

函数中的 C++ 数组

c++ - exp10 不同于 pow(10)

c++ - 如何在 C++ 中定义密封类?

c++ - 可以将 std::getline() 与移出的 std::string 一起使用吗?

c++ - Web 服务器端应用程序的 NTLM 身份验证

c++ - 对临时对象的常量引用不会延长其生命周期

c++ - gcc 错误?它莫名其妙地将数组衰减为指针,而clang没有

c++ - C++14 是否要求删除表达式必须调用 `void operator::delete(void*, std::size_t)` 而不是 `void::operator delete(void*)` ?

c++ - 重用构造函数。将右值传递给 const 左值并且不重复执行