#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 }};
Комментарии:
1. Спасибо за ответ, я сохраняю его в своей папке с интересными аспектами программирования, но для большинства проектов я, вероятно, буду использовать regular
SomeClass class;
, а не работать с ним, как было только что объяснено.2. Да, я настоятельно рекомендую ответы Роба и Титона. Это просто аккуратный трюк.
3. 1 Я как раз собирался опубликовать то же самое. Большое злоупотребление C :). Однако НЕ делайте этого, если это не для развлечения 🙂
Ответ №6:
Ваш const intamp; SomeClass::operator() (int x, int y) const
оператор не является статическим… стандарт C также не позволяет объявлять static
его. Поэтому для вызова он должен быть связан с экземпляром SomeClass
.