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

时间:2012-05-17 12:08:36

标签: c++ function const this member

这是我的代码

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转换为非const。

b.a = this;

有没有办法调用Func2而不必抛弃this的常量。由于Func2无论如何都是const函数,因此不会更改this

4 个答案:

答案 0 :(得分:3)

您必须将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指针是常量。

答案 1 :(得分:1)

Func2可能不会更改this,但b.a不会const,您可以随后更改它。尽管存在变通办法,例如mutableconst_cast,但没有正确的方法可以执行此操作。

这是设计错误的标志。

答案 2 :(得分:1)

是的,让A *保持不变:

class B {
public:
    const A *a

...
};

答案 3 :(得分:1)

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

public: const A* a

此时我应该提到B::Func2的常量是一个红色的鲱鱼,因为它与B::a的常量完全没有关系。 B::Func2const意味着不允许更改a的值;但是, 允许取消引用a并改变生成的对象。

现在,如果class Bconst进行const和非*a操作,则您的班级设计需要更改。如果您将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都保持独立的,适当类型的指向要访问的对象的指针。如果在setAB上使用D参数调用const A*,则仅设置B::a。如果在setA上使用D调用A*,则B::aD::a都会正确设置。这已成为可能,因为通过抽象setter后面的成员,您可以在其参数的constness上重载setter。