2012-05-17 2 views
2

Вот код, который я имеюВызова постоянной функции из другого класса объекта

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(); 
} 

Теперь очевидно, что это дает мне ошибку в линии, потому что я пытаюсь преобразовать из сопзЬ в неконстантный.

b.a = this; 

Есть ли способ вызова Func2 без откинуть константность this. Так как Func2 - функция const anyways, она не изменится this.

+0

Вы не можете изменить что-либо, связанное с объектом, когда у вас есть функция const. Либо вызовите его const * A a, либо удалите const из функции. – Martol1ni

ответ

1

Если class B всегда будет работать с *a как const объект, то, как другие сказали все, что нужно просто изменить декларацию

public: const A* a 

На этом этапе я должен упомянуть, что константа B::Func2 - это красная сельдь, потому что она абсолютно не связана с константой B::a. То, что B::Func2 равно const, означает, что не допускается изменять значение a; однако, это is разрешено разыгрывать a и мутировать полученный объект.

Теперь, если class B имеет как const и нефизических 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 */ } 
}; 

С помощью этой схемы как B и D сохранить независимость, соответственно типизированных указателей на объект, чтобы получить доступ. Если setA вызывается на B или на D с параметром const A*, то устанавливается только B::a. Если setA вызывается на D с A*, то оба B::a и D::a правильно установлены. Это стало возможным, потому что, абстрагировав член за сеттером, вы можете перегрузить setter на константу его параметра.

+0

Спасибо, это решает проблему :) – user1353535

3

Вы должны объявить A* константным:

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 указатель сопзЬ.

+0

Это решает проблему, но я не могу иметь «a» как const, потому что у B есть другие функции, которые могут изменять «a». Я знаю, что он виноват в моем дизайне, мог бы предложить лучший вариант. – user1353535

1

Func2 не может изменить this, но b.a не const, и вы можете изменить его позже. Нет правильного способа сделать это, хотя существуют обходные пути, такие как mutable или const_cast.

Это признак неисправного дизайна.

1

Да, сделать A * константу:

class B { 
public: 
    const A *a 

... 
}; 
Смежные вопросы