我在这 1 行代码中的语法有啥问题(指针、引用和取消引用哦,天哪)?

Posted

技术标签:

【中文标题】我在这 1 行代码中的语法有啥问题(指针、引用和取消引用哦,天哪)?【英文标题】:What is wrong with my syntax in this 1 line bit of code (pointers and references and dereferences oh my)?我在这 1 行代码中的语法有什么问题(指针、引用和取消引用哦,天哪)? 【发布时间】:2010-12-01 02:08:40 【问题描述】:

我遇到问题的代码是这一行:

result.addElement(&(*(setArray[i]) + *(rhs.setArray[j])));

我的类中的 + 运算符是这样重载的(有多种重载可以放在这个集合中,但它们都有一个相似的标题):

const Rational Rational::operator+(const Rational &rhs) const

上面代码中的setarrays都是指针数组,但是+操作符需要引用,这可能是问题所在。

结果的方法AddElement有这个头:

bool Set::addElement(Multinumber* newElement)

标题中的Multinumber* 是上面提到的Rational 的父类。我认为任何特定的代码都不重要。我很确定这是语法问题。

我的编译器错误是:

68: error: invalid conversion from 'const Multinumber*' to 'Multinumber*'

感谢您的帮助!

【问题讨论】:

addElement() 需要一个非常量对象,但 + 运算符返回一个 const 对象。为什么它返回一个 const 对象? 我想我不妨把它变成一个答案。 【参考方案1】:

问题在于const

bool Set::addElement(Multinumber* newElement) 应该是Set::addElement(const Multinumber* newElement)

【讨论】:

除非人们希望能够修改集合的元素。 operator + 函数返回 const 因为 Multinumber 和 Rational 类是不可变的对象,如果您将数字视为基本类型,则在适当的位置改变数字是没有意义的像一个int【参考方案2】:

您的 operator + 返回一个 const 对象。但是,addElement 需要一个非常量对象,这是您的编译器错误的来源。基本上,addElement 告诉您可以随意修改您的 Multinumber,但 operator + 开始您不要修改返回的值。

您应该只返回一个非常量对象,除非有充分的理由不这样做。毕竟你没有返回参考。

当然,如果你的 Set 中的数据应该是恒定的并且永远不会改变,你也可以让addElement 接受一个 const 指针,并确保它在内部处理任何地方的 const 指针。

【讨论】:

我试图避免这种情况,因为我的教授不喜欢非常量 operator+ 函数,但我想我真的可能不得不这样做。当然,那我还有一个问题,因为我必须将返回的对象作为动态分配的指针传递到集合中,但我不知道它是什么类型:Rational、Complex 或 Pair。你对此有什么想法吗? 再一次,如果它真的是常量,你的 addElement 可以接受一个 const 指针——但这意味着它也需要在内部将它存储为一个 const 指针,并且需要返回它作为其访问器中的 const 指针!至于你的另一个问题——它们都是从一个公共基类派生的吗? 他们是。它们都是从 Multinumber 基类定义的。【参考方案3】:

问题在于 addElement 需要一个非常量,而 operator+ 返回一个 const 对象。

代码的修复是如下所述的强制返回

addElement((Multinumber * )&( *(setArray[i]) + *(rhs.setArray[j])));

如果您不想强制转换,因为强制转换可能会破坏此处类型检查的目的,那么您必须更改 addElement 的签名。这取决于您的项目范围,可能会在其他地方以及该 API 是否公开以及其他开发人员正在使用它时产生影响。更改签名也会影响他们。

所以要明智地选择。

【讨论】:

Multinumber 没有工作运算符+重载。 multinumber operator+ 是 virtual Multinumber& operator+(Multinumber& rhs)return *this 无代码。所以我不能转换为多号。而且我不能强制转换为子类,因为层次结构是多态的,而且我不知道在任何给定时间它将是什么类型。不过谢谢你的建议。 投出const。坏的。非常糟糕。 我同意 EboMike ..但是如果问题是要摆脱 const 那么上面就是解决方案..或者正如我提到的那样更改签名...【参考方案4】:

此代码存在的问题比您通过在某处添加 const 或类型转换所能解决的问题要严重得多。

这段代码的结果最终会在某处发生崩溃,因为您传递了一个指向临时对象的指针。完成调用addElement 的代码行后,指针将悬空,并且尝试使用它指向的对象将导致废话(如果您正在读取对象)或堆栈损坏(如果您'重新写入对象)。

重新定义代码的最佳方法是将其更改为

bool Set::addElement(Multinumber newElement) //pass the Multinumber by value

并拨打addElement如下:

result.addElement(*setArray[i] + *rhs.setArray[j]);

请注意,我删除了所有多余的括号,因为* 的优先级低于[],因此setArray[i]setArray[i] 周围的括号是多余的。我认为这样的代码更具可读性。


真的,如果我能猜到这里发生了什么,setArraySet 类的内部存储,所以它的类型需要从Multinumber** 重新定义为Multinumber*,在这种情况下调用真的应该是

result.addElement(setArray[i] + rhs.setArray[j]);


编辑哎呀。以上都不会真正让你保持你的多态性。您需要在某个地方致电new Rational,而我能想到的唯一合理的地方是:

result.addElement( new Rational(*setArray[i] + *rhs.setArray[j]) );

这无需重新定义Set::addElement即可工作。


更好的解决方案是重新设计整个事物,使其不依赖于数字类的多态性(因为在大多数正常使用中,数字类确实不应该包装在指针中)。

【讨论】:

不幸的是,这是一个家庭作业,并且作业的重点是多态性。而且我试图使用 new 运算符,但我不能,因为层次结构是多态的,我不知道该集合在那时是否包含有理数、对数或复数。 :( 无论如何,谢谢。如果您能想到其他任何事情,我将不胜感激。我已经为此工作了好几天。 @Ross: 那么你可以让operator+ 调用new Rational 并返回一个指针(我认为这在现实世界的代码中是个坏主意),或者你可以创建一个新的@987654340 @ 执行此操作的函数。 天才!我能够在所有子类中做到这一点,然后删除了 operator+ 重载的 const 属性。谢谢谢谢谢谢。

以上是关于我在这 1 行代码中的语法有啥问题(指针、引用和取消引用哦,天哪)?的主要内容,如果未能解决你的问题,请参考以下文章

当您动态分配内存时,“指针类型”有啥意义?

您对 C、C++ 和 Java 中的指针、引用和句柄有啥深刻的理解?

SQL 存储过程中的“引用旧”和“引用新”有啥区别?

C++中如何区分引用和取地址符号&?

C ++中的变量和引用有啥区别? [复制]

在 Go 中使用指针有啥意义?