我想知道是否可以从const成员函数调用非const成员函数。在下面的示例中,First给出了编译器错误。我理解为什么它会出错,我想知道是否有办法解决它。
class Foo
{
const int& First() const
{
return Second();
}
int& Second()
{
return m_bar;
}
int m_bar;
}
我真的不想讨论这样做的智慧,我很好奇它是否可能。
答案 0 :(得分:31)
return (const_cast<Foo*>(this))->Second();
然后静静地哭。
答案 1 :(得分:10)
可能:
const int& First() const
{
return const_cast<Foo*>(this)->Second();
}
int& Second() { return m_bar; }
我不推荐这个;这是丑陋和危险的(使用const_cast
是危险的。)
最好将尽可能多的常用功能移动到辅助函数中,然后让const和非const成员函数尽可能少地工作。
对于像这样的简单访问器,从两个函数中return m_bar;
和从另一个函数调用一个函数一样容易。
答案 2 :(得分:3)
根据const
的定义,函数不应修改对象的状态。但如果它调用另一个非const成员,则对象的状态可能会被更改,因此不允许这样做。
我知道你说你不想听到这个,但我认为这对其他人来说很重要。
答案 3 :(得分:3)
const成员方法的限制来自编译时。如果你可以欺骗编译器,那么是的。
class CFoo
{
public:
CFoo() {m_Foo = this;}
void tee();
void bar() const
{
m_Foo->m_val++; // fine
m_Foo->tee(); // fine
}
private:
CFoo * m_Foo;
int m_Val;
};
这实际上废除了const成员函数的目的,所以在设计新类时最好不要这样做。知道有一种方法可以做到这一点是没有害处的,特别是它可以用来解决这些在const成员函数概念上没有很好设计的旧类。
答案 4 :(得分:2)
const
上的重载:
const int& Second() const
{
return m_bar;
}
您可以添加此方法并保留原始的非const版本。
答案 5 :(得分:1)
迭代器在此类似,并进行了一项有趣的研究。
const迭代器通常是“非常量”迭代器的基础,并且您经常会发现const_cast<>()
或C样式转换用于从子类中删除带有子代中访问器的const。
编辑: 评论是
我有一个zip迭代器,其中const一个继承自非const
这通常是错误的遗产结构(如果你说的是我认为你的意思),原因是孩子的限制不应该比父母少。
说你有一些算法采用你的zip迭代器,是否适合将const迭代器传递给非const?
如果你有一个const容器,只能问它一个const迭代器,但是const迭代器是从迭代器派生出来的,所以你只需要使用父对象上的特性来进行非const访问。
以下是传统stl模型
之后的建议继承的快速概述class ConstIterator:
public std::_Bidit< myType, int, const myType *, const mType & >
{
reference operator*() const { return m_p; }
}
class Iterator : public ConstIterator
{
typedef ConstIterator _Mybase;
// overide the types provided by ConstIterator
typedef myType * pointer;
typedef myType & reference;
reference operator*() const
{
return ((reference)**(_Mybase *)this);
}
}
typedef std::reverse_iterator<ConstIterator> ConstReverseIterator;
typedef std::reverse_iterator<Iterator> ReverseIterator;
答案 6 :(得分:0)
我发现自己试图调用一个继承的非const成员函数,但由于我使用的API,它实际上是const。最后,我找到了一个不同的解决方案:重新协商API,以便我继承的函数是正确的const。
并不总是可以协商对其他人功能的更改,但在可能的情况下这样做似乎比需要使用const_cast更清晰,更好,并且它也有利于其他用户。