C++ void方法和lambda“技巧”中的常数正确性

C++ void方法和lambda“技巧”中的常数正确性,c++,c++11,lambda,theory,c++14,C++,C++11,Lambda,Theory,C++14,我有一个方法,它接受一个对象的引用作为常量,这个方法不会改变这个方法的任何东西,常量表示,问题是这个方法也调用了类中的其他方法,它是无效的,不接受任何参数,也是虚的,这意味着扩展基类的类可以重写该方法,但它也必须是常量。例如: #include <iostream> class Boz { public: virtual void introduce() const = 0; }; class Foo { public: virtual void callable

我有一个方法,它接受一个对象的引用作为常量,这个方法不会改变这个方法的任何东西,常量表示,问题是这个方法也调用了类中的其他方法,它是无效的,不接受任何参数,也是虚的,这意味着扩展基类的类可以重写该方法,但它也必须是常量。例如:

#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;
}
如您所见,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;
    }
};
它可以工作,并且调用了可调用的方法。没有像将“const…”作为“this”参数传递这样的错误

我试图做的是调用callable而不需要常量,原因很简单:方法没有改变任何东西,他没有访问作为调用方方法参数传递的begin对象的权限,然后我们假设他不需要常量,但编译器会以这种方式抛出错误。真正的问题是可调用是虚拟的,类可以扩展基类,实现自己的可调用,并尝试调用其他方法,但如果不是const,则不能


我想知道的是,在不需要常量的情况下如何调用虚方法,原因是,我强迫扩展类和重写可调用方法的用户只调用const方法,这不是我想要的,当然我也理解lambda发生了什么,以及它为什么工作。

使用lambda的代码肯定不应该编译,它只是一个报告为的GCC错误,现在已在svn主干中修复,借

如果确实需要从常量函数调用非常量成员函数,则需要舍弃常量:

const_cast<Foo*>(this)->callable();
但这相当危险,至少有两个原因

如果对象被声明为常量,那么它是未定义的行为,例如常量Foo f;f、 卡勒博兹;这是一种未定义的行为

调用虚拟函数时,您不一定知道派生类的重写肯定不会修改任何内容。虚函数的全部要点是派生类可以做一些不同的事情,而基类不知道细节


我会更改您的设计,使您要调用的虚拟函数为const,或者调用方函数为non-const。其他任何东西都是危险的。

带有lambda的代码绝对不应该编译,它只是一个被报告为的GCC错误,现在已经在svn主干中修复了

如果确实需要从常量函数调用非常量成员函数,则需要舍弃常量:

const_cast<Foo*>(this)->callable();
但这相当危险,至少有两个原因

如果对象被声明为常量,那么它是未定义的行为,例如常量Foo f;f、 卡勒博兹;这是一种未定义的行为

调用虚拟函数时,您不一定知道派生类的重写肯定不会修改任何内容。虚函数的全部要点是派生类可以做一些不同的事情,而基类不知道细节


我会更改您的设计,使您要调用的虚拟函数为const,或者调用方函数为non-const。其他任何东西都是危险的。

您可以将非常量Boz&传递给调用者,除非您特别想传递右值给调用者……通过将参数声明为常量,您向调用者承诺不会更改参数的状态。如果你将参数传递给一个未知的方法,而这个方法也没有做出同样的承诺,你怎么能尊重这个承诺呢?Lambda技巧看起来不像是应该起作用的东西,因为它有效地丢弃了这个常量。clang不接受此代码,但g++接受。你需要const_cast来做类似的事情,或者,也许更好的主意,重新设计你的代码,这样你就不需要丢弃const了?据我所知,这是一个编译器错误。它不应该编译。你不应该使用const_cast。您应该已经决定是否需要Foo常量。如果您确实希望它是常量,请将const同时放在caller和callable上。如果没有,则从两个对象中删除常量。我说的是介于结束括号和开始括号之间的常量。你可以将非常量Boz&传递给调用者,除非你特别想传递右值给它……通过将参数声明为常量,你向调用者保证你不会改变参数的状态。如果你将参数传递给一个未知的方法,而这个方法也没有做出同样的承诺,你怎么能尊重这个承诺呢?Lambda技巧看起来不像是应该起作用的东西,因为它有效地丢弃了这个常量。clang不接受此代码,但g++接受。你需要const_cast来做这样的事情,或者,proba 更好的办法是重新设计代码,这样就不需要丢弃常量。但lambda发生了什么呢?据我所知,这是一个编译器错误。它不应该编译。你不应该使用const_cast。您应该已经决定是否需要Foo常量。如果您确实希望它是常量,请将const同时放在caller和callable上。如果没有,则从两个对象中删除常量。我说的是介于结束括号和开始括号之间的常数。