我有一个方法接受一个对象的引用作为const,这个方法不会改变方法的任何内容,而const表明,这个方法也调用了类中的其他方法, void,不接受任何参数,也是虚拟的,这意味着扩展基类的类可以覆盖方法,但它也需要是const。例如:
#include <iostream>
class Boz
{
public:
virtual void introduce() const = 0;
};
class Foo
{
public:
virtual void callable() const
{
// ...
}
void caller(const Boz& object) const
{
callable();
object.introduce();
}
};
class Bar : public Boz
{
public:
void introduce() const
{
std::cout << "Hi." << std::endl;
}
};
class Biz : public Foo
{
public:
void callable() const
{
std::cout << "I'm being called before the introduce." << std::endl;
}
};
int main(void)
{
Biz biz;
biz.caller(Bar());
return 0;
}
输出结果为:
I'm being called before the introduce.
Hi.
正如您所看到的,callable
必须是const才能被调用。如果我改变并这样做:
class Biz : public Foo
{
public:
void callable()
{
std::cout << "I'm being called before the introduce." << std::endl;
}
};
它将编译而不是抛出错误但是不会调用可调用方法,而是将虚拟调用为const。这很明显。
这里最棘手的部分:
class Foo
{
public:
virtual void callable()
{
// ...
}
void caller(const Boz& object) const
{
auto trick = [&] () { callable(); };
trick();
object.introduce();
}
};
class Biz : public Foo
{
public:
void callable()
{
std::cout << "I'm being called before the introduce." << std::endl;
}
};
它可以工作,并调用callable
方法。没有passing 'const ...' as 'this' argument
等错误。
我要做的是调用callable
而不需要是const,原因很简单:该方法不会改变任何东西,他无法访问开始的对象作为caller
方法的参数传递,然后我们假设他不需要const
,但编译器甚至会抛出错误。真正的问题是callable
是虚拟的,类可以扩展基类,实现自己的callable
并尝试调用其他方法,但如果它不是const
则不能。 / p>
我想要的就是知道如何在不需要const的情况下调用虚方法(原因几乎就是这样,我强迫用户扩展类并覆盖{ {1}}仅调用callable
方法的方法,这不是我想要的,当然也可以理解lambda会发生什么以及它的工作原理。
答案 0 :(得分:5)
带有lambda的代码肯定不应该编译,它只是一个GCC错误(报告为PR 60463和PR 60755),现在通过http://gcc.gnu.org/r210292 <修复在svn主干中/ p>
如果确实需要从const中调用非const成员函数,则需要抛弃constness:
const_cast<Foo*>(this)->callable();
但由于至少有两个原因,这是非常危险的
如果对象被声明为const
,那么它是未定义的行为,例如const Foo f; f.caller(boz);
是未定义的行为。
你正在调用一个虚函数,你不一定知道派生类'覆盖肯定不会修改任何东西。虚函数的重点是派生类可以做不同的事情,基类不知道细节。
我会更改您的设计,以便您要调用的虚函数为const
,或caller
函数为非const。其他任何事情都很危险。