yay*_*yuj 1 c++ theory lambda c++11 c++14
我有一个方法接受一个对象的引用作为const,这个方法不会改变方法的任何内容,而const表明,这个方法也调用了类中的其他方法,并且是无效的不接受任何参数,也是虚拟的,这意味着扩展基类的类可以覆盖方法,但它也需要是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;
}
Run Code Online (Sandbox Code Playgroud)
输出将是:
I'm being called before the introduce.
Hi.
Run Code Online (Sandbox Code Playgroud)
你可以看到callable
必须是const才能被调用.如果我改变并这样做:
class Biz : public Foo
{
public:
void callable()
{
std::cout << "I'm being called before the introduce." << std::endl;
}
};
Run Code Online (Sandbox Code Playgroud)
它将编译而不是抛出错误但是不会调用可调用方法,而是调用虚拟方法,因为它被定义为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;
}
};
Run Code Online (Sandbox Code Playgroud)
它工作,并callable
调用该方法.没有错误passing 'const ...' as 'this' argument
.
我正在尝试做的是调用callable
而不需要是const,原因很简单:该方法不会改变任何东西,他无法访问作为caller
方法的参数开始传递的对象然后我们假设他没有必要,const
但编译器甚至会抛出错误.真正的问题是callable
虚拟和类可以扩展基类,实现自己的,callable
并尝试调用其他方法,但如果不是这样,则不能const
.
我想要的就是知道如何在不需要const的情况下调用虚方法(原因很简单,我强迫扩展类的用户并覆盖callable
方法只调用const
方法,这不是我想要的),当然理解lambda会发生什么以及它为什么会起作用.
带有lambda的代码肯定不应该编译,它只是一个GCC错误(报告为PR 60463和PR 60755),现在已经在svn trunk中修复,http://gcc.gnu.org/r210292
如果你真的需要从const中调用一个非const成员函数,你需要抛弃constness:
const_cast<Foo*>(this)->callable();
Run Code Online (Sandbox Code Playgroud)
但至少有两个原因,这是非常危险的
如果对象被声明,const
那么它是未定义的行为,例如const Foo f; f.caller(boz);
未定义的行为.
你正在调用一个虚函数,你不一定知道派生类'覆盖肯定不会修改任何东西.虚函数的重点是派生类可以做不同的事情,基类不知道细节.
我会改变你的设计,以便你想要调用的虚函数const
,或者caller
函数是非常量的.其他任何事情都很危险.