2010-06-24 2 views
1

Я - прерывистый программист и, похоже, недавно забыл множество основ.Функция, возвращающая указатель на массив const 2-d (C++)

Я создал класс SimPars для хранения нескольких двумерных массивов; один показан ниже: demPMFs. Я собираюсь передать указатель на экземпляр SimPars другим классам, и я хочу, чтобы эти классы могли читать массивы с использованием функций доступа SimPars. Скорость и память важны.

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

Как написать функции доступа для массивов? Если меня интересует индекс n-го массива, как мне получить доступ к нему с помощью возвращаемого указателя? (Должен ли я писать отдельную функцию доступа для определенного индекса массива?) Что ниже, конечно, неверно.

// SimPars.h 
#ifndef SIMPARS_H 
#define SIMPARS_H 
#include "Parameters.h" // includes array size information 

class SimPars { 
public: 
    SimPars(void); 
    ~SimPars(void); 

    const double [][ INIT_NUM_AGE_CATS ] get_demPMFs() const; 

private: 
    double demPMFs[ NUM_SOCIODEM_FILES ][ INIT_NUM_AGE_CATS ]; 

}; 
#endif 


// SimPars.cpp 
SimPars::SimPars() { 
demPMFs[ NUM_SOCIODEM_FILES ][ INIT_NUM_AGE_CATS ]; 
// ...code snipped--demPMFs gets initialized... 
} 

//...destructor snipped 
const double [][ INIT_NUM_AGE_CATS ] SimPars::get_demPMFs(void) const { 
    return demPMFs; 
} 

Я был бы очень признателен за некоторые объяснения предлагаемых решений.

+0

Я уверен, что декларация члена 'double demPMFs [] [INIT_NUM_AGE_CATS];' является незаконной. Это действительно компилируется? – fredoverflow

+0

Спасибо, что поймали это. Исправлена ​​опечатка. У меня был размер в исходном коде. – Sarah

+0

Не могли бы вы подробно рассказать о том, чего вы на самом деле пытаетесь достичь? рассмотрите 2-мерный массив как массив указателей: 'demPMFs **', тогда вам не нужно указывать какой-либо размер в возвращаемом типе, как в 'const double [] [INIT_NUM_AGE_CATS] get_demPMFs() const;' ... – nus

ответ

3

В принципе, у вас есть три варианта: верните весь массив по ссылке, верните первую строку указателем или верните весь массив указателем. Вот реализация:

typedef double array_row[INIT_NUM_AGE_CATS]; 

typedef array_row array_t[NUM_SOCIODEM_FILES]; 

array_t demPMFs; 

const array_t& return_array_by_reference() const 
{ 
    return demPMFs; 
} 

const array_row* return_first_row_by_pointer() const 
{ 
    return demPMFs; 
} 

const array_t* return_array_by_pointer() const 
{ 
    return &demPMFs; 
} 

А вот случаи использования:

SimPars foo; 

double a = foo.return_array_by_reference()[0][0]; 
double b = foo.return_first_row_by_pointer()[0][0]; 
double c = (*foo.return_array_by_pointer())[0][0]; 

Как бы я вернуть только п-ю строку массива?

Опять же, у вас есть три варианта:

const array_row& return_nth_row_by_reference(size_t row) const 
{ 
    return demPMFs[row]; 
} 

const double* return_first_element_of_nth_row_by_pointer(size_t row) const 
{ 
    return demPMFs[row]; 
} 

const array_row* return_nth_row_by_pointer(size_t row) const 
{ 
    return demPMFs + row; 
} 
+0

Спасибо. Как я могу вернуть только n-ю строку массива? – Sarah

+1

@Sarah: Я обновил свой пост. В обоих случаях я предпочел бы первое решение, возвращая все, что вам интересно по ссылке. – fredoverflow

1
const double (* get_demPMFs() const)[INIT_NUM_AGE_CATS]; 

Или используйте typedef (но это не кажется чище ...).

class SimPars { 
    typedef const double (*ConstDemPMFType)[INIT_NUM_AGE_CATS]; 

    double demPMFs[NUM_SOCIODEM_FILES][INIT_NUM_AGE_CATS]; 
public: 
    ConstDemPMFType get_demPMFs() const; 
}; 

Обратите внимание, что вы не можете вернуть массив (g++ отказывается от компиляции). Но массив массива может быть разложен на указатель на массив, поэтому последний возвращается.

+0

'(* get_demPMFs() const)' -> ah, вот где скобки и константа должны уйти, я сражался с синтаксисом декларатора C в течение 5 минут и сдался, отступая к добрым typedef :) – fredoverflow

+1

@Fred this где «идентификация» превосходит. 'identity :: type * get_demPMFs() const;' –

0

Логически говоря есть этот вопрос с членом данных. Если пользователям разрешено изменять его или нет. Если вы хотите предоставить другому классу полный доступ к члену, вам не обязательно нужен getter/setter, особенно если вы единственный пользователь. Вы можете просто сделать участника общедоступным.

Если вашему классу было бы лучше контролировать доступ пользователей к члену, то вы можете использовать геттер только для обеспечения доступа только для чтения. Самый простой способ сделать это, если вы не хотите, чтобы получить все запутались в 2-мерных массивов просто имеют функцию встроенного забирающий элемент для пользовательского класса:

const double& getElem(int x, int y) const { return demPMF[x][y] } 

Это имеет смысл делать оценки проверяя здесь, но учитывая, что вы настаиваете на использовании массивов, и если ваш профилировщик докажет, что вы не можете себе это позволить, эта функция просто разрешит доступ к вашему массиву.

Если вы хотите уточнить, отправьте комментарий ...

+0

Как проходит весь массив вне ссылки const, менее безопасный? – fredoverflow

+0

O, это определенно не менее безопасно, но это более запутанно, по крайней мере для меня это намного проще. Я все еще пытаюсь выработать ваш синтаксис и ответы Кенни. – nus

Смежные вопросы