C++返回一个对象抛出一个接口

发布于 2024-11-19 23:25:28 字数 1009 浏览 7 评论 0原文

我想设计一个通用接口,它有一个方法,可以让我将两个具有该接口的对象相乘,并返回一个同一类的新对象作为结果。为了简单起见,我将只关注一个实现该接口的类。 问题:我的问题是返回的对象。 让我们看看:

拥有接口之前的目标:

class C {
  public:
  int get() { return v; }
  void set(int value) { v = value; }
  C operator * (C &l) {
    C r;
    r.set(get() * l.get());
    return r;
  }

  private:
  int v;
};

在这种情况下,operator* 方法返回 C 类型的对象,但不是引用(请记住这一点)。它利用了返回值优化。 现在,让我们来解决这个问题: 在这种情况下,我想设计一个接口:

struct I {
  virtual int get() = 0;
  virtual void set(int value) = 0;
  virtual I& operator * (I &l) = 0;
};

在这种情况下,我不能将返回类型 I (按值)用于operator* 方法,因为 I 是抽象的。好的,让我们讨论问题:

class C : public I {
  public:
  int get() { return v; }
  void set(int value) { v = value; }
  I& operator * (I &l) {
    C r;
    r.set(get() * l.get());
    return r; //  warning: reference to local variable ‘r’ returned
  }

  private:
  int v;
};

这里的问题是我正在返回对局部变量的引用。

我怎样才能以正确的方式做到这一点,而不使用动态分配?

提前致谢。

I want to design a common interface which has a method that let me multiply two object which has this interface, returning a new object of the same class as the result. In order to keep it easy, I'm going to focus just on one class which implement this interface.
The problem: My problem is the returned object.
Let's see:

The goal before having an interface:

class C {
  public:
  int get() { return v; }
  void set(int value) { v = value; }
  C operator * (C &l) {
    C r;
    r.set(get() * l.get());
    return r;
  }

  private:
  int v;
};

In this case, the operator* method return an object of type C, but not a reference (keep this in mind). It takes advantage of the return value optimization.
Now, let's arrive to the problem:
In this case I want to design an interface:

struct I {
  virtual int get() = 0;
  virtual void set(int value) = 0;
  virtual I& operator * (I &l) = 0;
};

In this case, I can't use a returned type I (by value) for the operator* method, because I is abstract. OK, let's go to the problem:

class C : public I {
  public:
  int get() { return v; }
  void set(int value) { v = value; }
  I& operator * (I &l) {
    C r;
    r.set(get() * l.get());
    return r; //  warning: reference to local variable ‘r’ returned
  }

  private:
  int v;
};

The problem here is I'm returning a reference to a local variable.

How can I do this, in the right way, without using dynamic allocation?

Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

々眼睛长脚气 2024-11-26 23:25:28

如果不使用动态分配,就无法以这种多态方式做到这一点。

您确定乘法以多态方式确实有意义吗?如果是这样,您将必须返回动态分配的指针并管理其生命周期(可能使用智能指针)。但在这种情况下,它不符合正常的语义 if operator* 因此您应该创建一个特殊的函数来完成这项工作。

另请注意,您有一些不符合 C++ 习惯的怪癖。 get 应该是一个 const 方法,operator* 的参数应该是 const 引用或值(没有人希望 operator* 修改一个其操作数,因为这违反了最小意外原则)。通常,operator* 按值返回其结果,以防止在运算符不按值返回时混淆谁拥有任何已分配的返回内存。

You can't do this in such a polymorphic way without using dynamic allocation.

Are you sure that multiplication is really meaningful in a polymorphic way? If so, you'll have to return a dynamically allocated pointer and manage its lifetime (possibly with a smart pointer). But in this case it doesn't fit the normal semantics if operator* so you should probably create a special function to do that work.

Also note that you have a few quirks that aren't C++-idiomatic. get should be a const method, the parameter to your operator* should be by const reference or value (no one wants operator* to modify one of its operands as that violates the principle of least surprise). And typically operator* returns its result by value to prevent confusions over who owns any allocated returned memory if the operator didn't return by value.

不忘初心 2024-11-26 23:25:28

返回指向动态分配对象 (I*) 的指针,或按值返回 C

返回引用是可能的,但它会令人困惑,因此不要执行以下操作:

virtual I &operator*(I &l) {
    C *r = new C();
    r->set(get() * l.get());
    return *r; //  warning: reference to local variable ‘r’ returned
}

这里的问题是,虽然返回值看起来像一个值,但它仍然必须使用不寻常的语法delete &r;进行删除

Either return a pointer to a dynamically allocated object (I*) or return a C by value.

Returning a reference is possible, but it's confusing, so don't do the following:

virtual I &operator*(I &l) {
    C *r = new C();
    r->set(get() * l.get());
    return *r; //  warning: reference to local variable ‘r’ returned
}

The problem here is that, although the return value looks like a value, it must still be delete'd with the unusual syntax delete &r;

夜唯美灬不弃 2024-11-26 23:25:28

我相信在这种情况下您应该使用 operator*= 而不是 operator*

operator*=中,你返回一个对*this的引用,它不是一个局部变量,所以返回是可以的。

operator* 情况下,它应该是 const 并且您需要按值返回(好吧,该语言并没有强迫您这样做,但是如果您正在进行乘法,它很可能是最重要的)明智的做法)。我不确定如何使这样的东西与虚拟函数一起工作,我通常会使用模板(尽管使用这种方法会损失运行时多态性)。

I believe you should be using operator*= not operator* in this case.

In the operator*= you return a reference to *this, which is not a local variable, so it's ok to return.

In the operator* case, it should be const and you need to return by value (well, the language doesn't force you to, but if you're doing multiplication, it's very likely it's the most sensible thing to do). I'm not sure how to make such a thing work with virtual functions, I would generally use templates (though you loss run time polymorphism with such an approach).

各自安好 2024-11-26 23:25:28

编辑:你想要的是可能的......但是这是一个非常糟糕的主意。

不分配内存的要求是完全不可能的。乘法需要创建一个新对象(根据定义),并且需要在堆上创建一个多态对象(如果您想避免切片并通过接口引用它)。

但是,如果您仍然想使用多态 a,b,c 编写 I* result = a*b*c ,您可以通过使用代理对象并使用一些隐式方法来完成此操作铸造..

您可以创建一个代理对象,并抛出一些隐式铸造:

   struct Iref {
      I* ref;
      Iref(I* aref):ref(aref){};
      operator I*() { return ref; }   
      Iref operator * (I& b);
      Iref operator * (Iref b);
      Iref operator * (I* b);
   };

使用此代理和适当编写的方法,您最终可以得到:

int main()
{
  C a(1), b(2), c(3);
  I* result = a*b*c;
  return 0;
}

剩下的问题是固有的内存泄漏。要么在应用程序中使用垃圾收集器。我对这些没有经验,我只知道这是可能的。或者让代理对象处理内存释放。

这个相当复杂的技巧应该表明operator*和多态性一起不是一个好主意。还有其他问题,就像多态性一样,您最终可能会得到具有不同结果的 a * bb * a

Edit: What you want is possible ... however it's a really bad idea.

The requirement for no memory allocation is flatly impossible. Multiplication needs to create a new object (by definition), and a polymorphic object needs to be created on the heap (if you want to avoid slicing and refer to it by the interface).

However if you still want to write I* result = a*b*c with polymorphic a,b,c you can accomplish this by using a proxy object and use some implicit casting..

You can create a proxy object with some implicit casting thrown in:

   struct Iref {
      I* ref;
      Iref(I* aref):ref(aref){};
      operator I*() { return ref; }   
      Iref operator * (I& b);
      Iref operator * (Iref b);
      Iref operator * (I* b);
   };

With this proxy and appropiately written methods you can end up with:

int main()
{
  C a(1), b(2), c(3);
  I* result = a*b*c;
  return 0;
}

The remaining problem is the inherent memory leak. Either you use a garbage collector with your application. I have no experience with these, I just know it's possible. Or you let the proxy object handle memory deallocation.

This rather elaborate trickery should show how operator* and polymorphism together are not a good idea. There are other problems, as with polymorphism you may end up with a * b and b * a having different results.

洛阳烟雨空心柳 2024-11-26 23:25:28

1 - 您不能返回类型为“I”(抽象类型)的对象实例
2 - 如果您想返回一个对象,而不是指针,您应该使用普通返回类型('C')。其他方式:使“I”不抽象并返回“I”。
3 - 推荐的方式:仅返回 I* 并且不要忘记稍后删除该对象。

1 - You cannot return an object instance typed like 'I' (abstract type)
2 - If You want to return an object, not a pointer, You should use the normal return type ('C'). Other way: make 'I' not abstract and return 'I'.
3 - The recommended way: return just I* and don't forget to delete the object later.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文