Позвольте мне предпочесть, что я в основном развивается в С# и развитии C++, которые я сделал, не полностью использовал язык C++. Теперь я пытаюсь использовать язык так, как он был предназначен, и я вытягиваю свои волосы с объявлениями const в переданных аргументах. Раньше я никогда не использовал их или не взламывал свой путь, чтобы заставить их работать с STL.
Мое понимание, что я создам следующую функцию, когда я хочу использовать o как readonly в функции:
void foo(const MyClass* o);
Итак, вот моя проблема... сначала код:
#include <iostream>
#include <string>
using namespace std;
///////////////////////////////////////////////////////////
// Classes are defined in the one file for an easy post.
///////////////////////////////////////////////////////////
class ClassA {
private: // member variables
string m_name;
public: // constructors
ClassA(const string& name = "") : m_name{name} {}
virtual ~ClassA() { }
public: // accessors
const string& name() const { return m_name; }
void setName(const string& value) { m_name = value; }
};
class ClassB {
private: // member variables
string m_name;
ClassA m_child;
public: // constructors
ClassB(const string& name = "") : m_name{name} {}
virtual ~ClassB() { }
public: // accessors
const string& name() const { return m_name; }
void setName(const string& value) { m_name = value; }
ClassA* child() { return &m_child; }
void setChild(const ClassA* value) { m_child = *value; }
};
///////////////////////////////////////////////////////////
// Protoptypes are not used to save space for the post.
void doSomethingA(const ClassA* o) {
cout << "name = " << o->name() << endl << endl;
}
void doSomethingB(const ClassB* o) {
cout << "name = " << o->name() << endl << endl;
doSomethingA(o->child());
}
///////////////////////////////////////////////////////////
int main(int argc, char** argv) {
ClassA a { "My Class A" };
ClassB b { "My Class B" };
b.setChild(&a);
b.child()->setName("My New Name");
doSomethingB(&b);
return 0;
}
В main() компилятор (g++ версия 4.7.2) не работает в doSomethingB:
doSomethingA(o->child());
с ошибкой: передача 'const ClassB' как 'this' аргумента 'ClassA * ClassB :: child()' отбрасывает квалификаторы [-fpermissive]
Теперь я передаю свои классы функциям в качестве указателей. Я планирую всегда использовать указатели, потому что у меня проблема с параметрами reference/pointer. Я выбираю один, указатели и придерживаюсь его. Итак doSomethingA и doSomethingB Я хочу, чтобы это было const, чтобы сообщить программисту, что их класс не изменяется. Но мне нужна только одна версия child(), которую я хочу использовать иногда как "только для чтения", а в другое время позволяет пользователю изменять данные в дочернем объекте (не лучший метод, я предоставляю это, но некоторые используют случаи, когда мне это нужно). Я даже попробовал:
doSomethingA(const_cast<const ClassA*>(o->child()));
Но это не сработало.
Раньше я удалял объявления const в функциях, чтобы сделать что-то вроде этой работы, но теперь я хочу использовать надлежащее C++. Помоги пожалуйста.
Вы пытаетесь получить доступ к функции non-const против объекта const. Вам нужно сделать функцию const
:
const ClassA* child() const { return &m_child; }
Вы также можете предоставить версию const и non-const:
ClassA* child() { return &m_child; }
const ClassA* child() const { return &m_child; }
Таким образом, вы можете вызывать неконстантные методы в ClassA
если у вас есть неконстантный объект.
пытаться
ClassA* child() const { return &m_child; }
или
const ClassA* child() const { return &m_child; }
сохранить константную корректность
Кроме того, вам не нужно использовать указатели, если вы не планируете передавать nullptr. Таким образом, вы можете сделать следующее:
void doSomethingB(const ClassB& o);
// in class ClassB
const ClassA& child() const { return m_child; }
ClassA& child() { return m_child; }
Ссылки все еще хранят полиморфные вещи так же, как указатели.
const
указатель тоже. Чтобы другие части кода OP работали, child
должен быть перегружен на const
.
child()
const
?