从另一个类对象调用常量函数

Calling constant function from another class object

本文关键字:常量 函数 调用 对象 另一个      更新时间:2023-10-16

这是我的代码

class A
{
public:
    void Func1() const;
};
class B
{
public:
    A* a;
    void Func2() const
    {
        // do something with 'a'
    }
};
void A::Func1() const
{
    B b;
    b.a = this;
    b.Func2();
}

现在显然这给了我一个错误,因为我正在尝试从 const 转换为 non-const。

b.a = this;

有没有办法在不抛弃this的恒常性的情况下调用Func2.由于Func2无论如何都是常量函数,因此它不会更改this

您必须将A*声明为 const:

class A
{
public:
    void Func1() const;
};
class B
{
public:
    const A* a;
    void Func2() const
    {
        // do something with 'a'
    }
};
void A::Func1() const
{
    B b;
    b.a = this;
    b.Func2();
}

因为在A::Func1中,this指针是常量。

如果class B总是将*a作为const对象使用,那么正如其他人所说,只需将声明更改为

public: const A* a

在这一点上,我应该提到B::Func2的恒定性是一条红鲱鱼,因为它与B::a的恒定性完全没有关系。B::Func2 const意味着不允许更改a的值;但是,允许取消引用a并改变生成的对象。

现在,如果class B*a方面同时具有const和非const操作,那么您的类设计需要更改。如果您切换class B使用上述const A* a,并添加另一个封装所有突变操作的class D : public B,那就更好了。此外,a应隐藏在属性设置器后面;这使您可以执行以下操作:

class B {
    const A* a;
public:
    void setA(const A* a) { this->a = a; }
    void Func2() const {}
};
class D : public B {
    A* a;
public:
    using B::setA;
    void setA(A* a) { 
        this->a = a;
        static_cast<B*>(this)->setA(const_cast<const A*>(a));
    }
    void Func3() { /* do something to D::a */ }
};

使用此方案,BD 都保持独立的、适当类型的指向要访问的对象的指针。如果在B或具有const A*参数的D上调用setA则仅设置B::a。如果在具有A*D上调用setA,则B::aD::a都设置正确。这已经成为可能的,因为通过抽象 setter 后面的成员,您可以在其参数的恒定性上重载 setter。

Func2可能不会更改this,但b.a不是const,之后您可以自由更改它。没有正确的方法可以做到这一点,尽管存在解决方法,例如 mutableconst_cast .

这是设计错误的标志。

是的,使A *常量:

class B {
public:
    const A *a
...
};