我在这 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]
周围的括号是多余的。我认为这样的代码更具可读性。
真的,如果我能猜到这里发生了什么,setArray
是Set
类的内部存储,所以它的类型需要从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 行代码中的语法有啥问题(指针、引用和取消引用哦,天哪)?的主要内容,如果未能解决你的问题,请参考以下文章