Создать экземпляр из статического метода - PullRequest
1 голос
/ 03 июня 2010

скажем, я хочу, чтобы мои пользователи использовали только один класс, скажем SpecialData. Теперь у этого класса данных будет много методов, и в зависимости от типа данных, методы делают разные вещи, внутренне, но возвращают внешне похожие результаты. Поэтому я хотел иметь один «открытый» класс и другие «частные», дочерние классы, которые могли бы изменить поведение методов и т. Д. *

Было бы на удивление проще для некоторых типов данных, которые нужно собрать, сделать что-то вроде этого:

SpecialData& sm = SpecialData::new_supermatrix();

и new_supermatrix () будут возвращать экземпляр SuperMatrix, который наследуется от большинства вариантов поведения SpecialData.

мой заголовок:

static SpecialData& new_supermatrix();

мой cpp:

SpecialData& SpecialData::new_supermatrix()(){
  return SuperMatrix(MATRIX_DEFAULT_MAGNITUDE,1000,1239,FLOAT32,etc...);
}

Проблема в том, что я получаю эту ошибку, которая, вероятно, логична из-за обстоятельств:

неверная инициализация неконстантной ссылки типа ‘SpecialData &’ из временного типа ‘SpecialData’

Итак, есть идеи?

Ответы [ 7 ]

3 голосов
/ 04 июня 2010

Ну, у вас есть три варианта:

a) В любом случае вы хотите иметь только один экземпляр SuperMatrix. Затем перейдите к маршруту статического члена-функции, как уже было предложено.

б) Вы хотите создать несколько экземпляров. Тогда у вас есть для возврата указателя вместо ссылок и создания объектов с помощью new (т.е. return new SuperMatrix(...).

c) В качестве альтернативы варианту b вы также можете вернуть просто объект, т.е.

SpecialData SpecialData::new_supermatrix()(){
return SuperMatrix(MATRIX_DEFAULT_MAGNITUDE,1000,1239,FLOAT32,etc...);
}

Однако, для этого требуется оператор (глубокого) копирования (по умолчанию его будет недостаточно, чем обычно), и это означает, что объект создается в стеке, затем копируется и эта копия возвращается. Хорошо, что это не приведет к утечке памяти, если вы на самом деле не получите результат в переменную. Плохо то, что если объект очень большой, это может занять очень много памяти и времени.

Независимо от того, что вы собираетесь с этим делать, эти решения являются взаимоисключающими, как технически, так и логически. ;)

2 голосов
/ 04 июня 2010

Простой ответ - вы не можете использовать такие ссылки. Ваша функция new_supermatrix возвращает безымянное временное значение, которое вы пытаетесь связать с неконстантной ссылкой - C ++ позволяет только таким значениям связываться с константными ссылками. Если вы хотите писать подобные функции, вам нужно заставить их возвращать указатель на динамически размещенный объект или придерживаться возврата значения, но назначить возвращаемое значение другому значению в вызывающем коде.

1 голос
/ 04 июня 2010

У этого кода есть несколько проблем. Прежде всего, вы, вероятно, хотите использовать здесь указатели вместо ссылок. Возврат ссылки на объект, созданный в стеке, как вы делаете в new_supermatrix, почти сразу приведет к падению. Он должен быть выделен с помощью new и передан обратно как указатель, если вы этого хотите, но я не совсем уверен, что вы пытаетесь сделать. Но в любом случае, именно это и является причиной вашей ошибки: вы возвращаете ссылку на временную переменную.

0 голосов
/ 04 июня 2010

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

Читайте о шаблонах креативного дизайна . Наиболее близким к тому, что вы хотите сделать, является шаблон Factory Method .

0 голосов
/ 04 июня 2010

Вы не должны возвращать ссылку на временный / локальный объект.

Эта и многие другие распространенные ошибки, которых следует избегать, описаны в книге Мейерса, Эффективный C ++ .

0 голосов
/ 04 июня 2010

В вашем методе вы можете использовать static:

SpecialData& SpecialData::new_supermatrix()(){
  static SuperMatrix supermatrix(MATRIX_DEFAULT_MAGNITUDE,1000,1239,FLOAT32,etc...);
  return supermatrix;
}
0 голосов
/ 04 июня 2010

Вам действительно нужно использовать оператор new. Создание, которое вы получаете return SuperMatrix(MATRIX_DEFAULT_MAGNITUDE,1000,1239,FLOAT32,etc...);, выделяет объект в стеке, который очищается при возврате функции (что он делает в той же строке). Использование new приводит к его выделению в куче.

...