Правильное моделирование классов с использованием C ++ и const

0

Позвольте мне предпочесть, что я в основном развивается в С# и развитии 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++. Помоги пожалуйста.

  • 0
    Вы пытались сделать функцию child() const ?
  • 4
    «Я планирую всегда использовать указатели, потому что у меня проблема с опциями ссылки / указателя». просто покупает вам кучу проблем. не делай этого
Показать ещё 3 комментария
Теги:
const

2 ответа

0
Лучший ответ

Вы пытаетесь получить доступ к функции 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 если у вас есть неконстантный объект.

  • 0
    Примечательно, что в этом нет необходимости, если он использовал ссылки вместо указателей
  • 0
    Та же проблема со ссылками. Я не знал, что ты мог сделать это. Я думал, что следовал правилу, когда нельзя перегружать функцию, единственное отличие - тип возвращаемого значения. Как int foo (); и двойной foo (); не допускаются Чего я сейчас не понимаю, так это int foo () и const int foo (). Почему это отличается как функция-член.
1

пытаться

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

Ссылки все еще хранят полиморфные вещи так же, как указатели.

  • 0
    Возвращаемый тип должен быть const указатель тоже. Чтобы другие части кода OP работали, child должен быть перегружен на const .

Ещё вопросы

Сообщество Overcoder
Наверх
Меню