Доступ к статическому массиву в классе с помощью перегруженного operator ()

#c

#c

Вопрос:

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

Моя проблема в том, как получить доступ к статическому массиву в классе с помощью перегруженного operator ().

Main.cpp:

 class SomeClass
{
public:
    static const int a[2][2];

    const intamp; operator() (int x, int y) const;
};
  

Прямо под ним я определяю массив a:

 const int SomeClass::a[2][2] = {{ 1, 2 }, { 3, 4 }};
  

Вот перегруженный оператор:

 const intamp; SomeClass::operator() (int x, int y) const
{
    return a[x][y];
}
  

В main() я хочу получить доступ к 2D-массиву «a», просто используя SomeClass(1, 1) which shloudl возвращает 4. Но когда я пытаюсь скомпилировать main следующим образом:

 int main(void)
{
    cout << SomeClass(1, 1) << endl;

    return 0;
}
  

Я получаю эту ошибку:

 PretizeniOperatoru.cpp: In function ‘int main()’:
PretizeniOperatoru.cpp:22:22: error: no matching function for call to ‘Tabulka::Tabulka(int, int)’
PretizeniOperatoru.cpp:22:22: note: candidates are:
PretizeniOperatoru.cpp:5:7: note: SomeClass::SomeClass()
PretizeniOperatoru.cpp:5:7: note:   candidate expects 0 arguments, 2 provided
PretizeniOperatoru.cpp:5:7: note: SomeClass::SomeClass(const SomeClassamp;)
PretizeniOperatoru.cpp:5:7: note:   candidate expects 1 argument, 2 provided
  

Я понял, что не знаю, в чем проблема. Кажется, что вызывается конструктор класса. Кажется, что я создаю класс вместо доступа к массиву.

Что это значит? Есть ли какой-либо способ сделать массив таким, или было бы лучше нарушить правила инкапсуляции и определить его как глобальный? Означает ли это, что перегруженные операторы нельзя использовать для доступа к статическим массивам?

Когда я делаю это таким образом, он компилируется нормально:

 int main(void)
{
    SomeClass class;
    cout << class(1, 1) << endl;

    return 0;
}
  

Спасибо за ответ и надеюсь, что моя проблема имеет смысл. Я не использовал оператор [] для доступа, потому что его сложнее реализовать, чем () .

Комментарии:

1. Этот второй фрагмент не компилируется. class является ключевым словом.

2. @delnan — О да, извините за это, я написал первое, о чем я подумал.

Ответ №1:

Вы не можете создать статический operator() массив. Синтаксис SomeClass(1, 1) пытается вызвать несуществующий конструктор, для SomeClass которого требуется два целых числа. у вас должен быть экземпляр объекта для вызова operator() , как вы делали во втором примере (за исключением того, что это class ключевое слово).

Ответ №2:

Вам необходимо создать экземпляр объекта вашего класса для доступа к его членам. Попробуйте использовать

 cout << SomeClass()(1, 1) << endl;
  

вместо этого, создание экземпляра временного и использование его operator() .

Комментарии:

1. Большое спасибо, это работает. Хорошо, если я понимаю это сейчас, означает ли это, что ключевое слово ‘static’ указывает, что массив будет выделен в начале программы? Но в этом случае создание его снова SomeClass()(1,1) означает, что он снова выделяется с целью cout и на данный момент он существует дважды в оперативной памяти, да?

2. @Mimars: Нет. Массив является статическим и выделяется только один раз, но operator() является нестатической функцией-членом (как и все перегрузки операторов) и, следовательно, нуждается в экземпляре для работы. В вашем случае экземпляр пуст (нет данных), но все равно необходим.

3. Вау, круто. Я знал, почему решил изучать программирование… Еще раз благодарю вас за быстрые ответы, ваших ответов достаточно.

Ответ №3:

Вы не можете перегружать операторы и делать их статическими.

При этом вы можете перегрузить свой operator и получить доступ к члену из объекта типа SomeClass :

 SomeClass s;
s(1,2);
  

Ответ №4:

 cout << SomeClass(1, 1) << endl;
  

Эта строка создает временный объект типа SomeClass и передает этот объект operator<< .

Вы хотите создать временный объект, вызвать operator() и передать результат в operator<< :

 cout << SomeClass()(1,1) << "n";
  

P.s. Никогда не используйте endl , когда вы имеете в виду 'n' .

Комментарии:

1. Спасибо. Просто еще один вопрос — почему вы рекомендуете не использовать endl , но n ? Я читал, что это хорошо, потому что он также очищает выходной поток.

2. @Mimars — Это плохо, потому что он также сбрасывает выходной поток, что сравнительно дорого. Многие люди всегда используют endl для каждого конца строки. Это заставляет их программы запускать v-e-r-y s-l-o-w-l-y при записи больших выходных наборов на диск.

Ответ №5:

Это можно сделать, если вы хитрый, но это некрасиво. Добавьте переменную для хранения последнего результата, конструктор, который устанавливает эту переменную на основе параметров x and y , и оператор int() для выполнения преобразования. Вероятно, вы также захотите перегрузить operator<< .

 class SomeClass
{
public:
    static const int a[2][2];
    mutable int resu<

    SomeClass() {}
    SomeClass(const SomeClassamp; r) :result(r.result) {}
    SomeClass(int x, int y) :result(a[x][y]) {}
    int operator() (int x, int y) const {return result=a[x][y];}
    operator int() const {return resu<}
    friend ostreamamp; operator<<(ostreamamp; o, const SomeClassamp; r) {return o<<r.resu<}
};
const int SomeClass::a[2][2] = {{ 1, 2 }, { 3, 4 }};
  

http://ideone.com/gQJz5

Комментарии:

1. Спасибо за ответ, я сохраняю его в своей папке с интересными аспектами программирования, но для большинства проектов я, вероятно, буду использовать regular SomeClass class; , а не работать с ним, как было только что объяснено.

2. Да, я настоятельно рекомендую ответы Роба и Титона. Это просто аккуратный трюк.

3. 1 Я как раз собирался опубликовать то же самое. Большое злоупотребление C :). Однако НЕ делайте этого, если это не для развлечения 🙂

Ответ №6:

Ваш const intamp; SomeClass::operator() (int x, int y) const оператор не является статическим… стандарт C также не позволяет объявлять static его. Поэтому для вызова он должен быть связан с экземпляром SomeClass .