Форум программистов, компьютерный форум CyberForum.ru

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 31, средняя оценка - 4.90
Влад1966
0 / 0 / 0
Регистрация: 08.06.2009
Сообщений: 4
#1

Как правильно инициализировать статические члены класса? - C++

07.07.2009, 04:10. Просмотров 3748. Ответов 10
Метки нет (Все метки)

Я новичок и заранее прошу прощение за тупые вопросы. Имеются два класса: Solution и Pool. Pool состоит из нескольких обьектов класса Solution. Эти обьекты отличаются только переменными *x и y. Все остальные члены одинаковы: **a, n, yFunc. Чтобы предотвратить копирование **a и n во все обьекты Solution, я обьявил их как static. Вопрос такой: правильно ли я инициализирую **a и n внутри конструктора Pool? Может имеется другой, более элегантный способ глобального использования **a и n во всех обьектах Solution. Как мне поступить с функцией yFunc, которая тоже общая для всех обьектов Solution? Заранее спасибо!

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
class Solution
{
    double *x;
    double y;
    static double **a; // общие для всех обьектов класса
    static int n; // общий для всех обьектов класса
public:
    static void StaticSet(int,double**)
    Solution();
    ~Solution();
    double yFunc(); // хотелось бы иметь одну версию этой функции для всех обьектов данного класса
}
 
Solution::StaticSet(int numx,double **coef)
{
    n=numX;
    a = new double*[2];
    for(int i=0;i<2;i++) a[i] = new double[n];
    for(int i=0;i<2;i++) 
        for(int j=0;j<n;j++)
            a[i][j] = coef[i][j];
}
 
Solution::Solution()
{
    srand(time(0));
    for(int j=0;j<n;j++)
        x[j] = 2.0*(rand()/(double)RAND_MAX-0.5);
}
 
Pool::Pool(int numSols, int numX, double **coef)
{
    poolSize = numSols;
    Solution::StaticSet(numX,coef); // правильно ли это?
    for(int i=0;i<poolSize;i++)
        sols.push_back(new Solution());
}
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
07.07.2009, 04:10     Как правильно инициализировать статические члены класса?
Посмотрите здесь:
Как инициализировать статические члены класса C++
Как инициализировать члены класса, являющегося параметром шаблона C++
C++ Как правильно инициализировать данные-члены строкового типа в реализации функции-члена?
C++ Статические члены класса
C++ Статические члены класса
Статические массивы, члены класса C++
C++ Где инициализировать члены класса CTreeCtrl?
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Alexiski
Любитель давать советы
338 / 130 / 2
Регистрация: 12.01.2009
Сообщений: 511
07.07.2009, 05:19     Как правильно инициализировать статические члены класса? #2
Цитата Сообщение от Влад1966 Посмотреть сообщение
Вопрос такой: правильно ли я инициализирую **a и n внутри конструктора Pool? Может имеется другой, более элегантный способ глобального использования **a и n во всех обьектах Solution.
Со статикой, вроде правильно, а вот нестатический *x в конструкторе надо обязательно разместить перед заполнением. И еще хорогий тон - все, что создается в конструторе, обязательно уничтожать в деструкторе.

Цитата Сообщение от Влад1966 Посмотреть сообщение
Как мне поступить с функцией yFunc, которая тоже общая для всех обьектов Solution?
Функции, которые члены класса, и так общие для всех объектов.
Тут главный вопрос другой: должна ли эта функция работать с полями x и y конкретного класса? Если не должна, то ее можно сделать статической. Если должна, то ее делать статической нельзя.

И хотя нестатическая функция вызывается через конкретный объект, это не значит, что она своя у каждого объекта. Фактически, этот объект просто передается ей как скрытый параметр.
Влад1966
0 / 0 / 0
Регистрация: 08.06.2009
Сообщений: 4
07.07.2009, 07:25  [ТС]     Как правильно инициализировать статические члены класса? #3
Большое спасибо. Забыл я про память для *x. Функция yFunc работает с статическими и нестатическими параметрами. Как я правильно Вас понял, её нельзя делать статической.
Evg
Эксперт CАвтор FAQ
17469 / 5707 / 362
Регистрация: 30.03.2009
Сообщений: 15,663
Записей в блоге: 26
07.07.2009, 09:10     Как правильно инициализировать статические члены класса? #4
> Pool состоит из нескольких обьектов класса Solution

При этом я вижу только один вызов StaticSet В конструкторе

А вообще код на самом деле написан неверно. При появлении нового объекта класса Pool будет вызываться конструктор Pool, который вызовет StaticSet, а там массив a выделится по-новой.

Правильно писать что-то типа того:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Solution
{
  ...
  static double **a = NULL ; // <------ статически инициализируем NULL'ом
  ...
}
 
Solution::StaticSet(int numx,double **coef)
{
  ...
  if (a != NULL)  // <-------- чтобы при повторном заходе в этот метод не перевыделять память
  {
    a = new double*[2];
    ...
  }
  ...
}
Здесь я просто на пальцах пояснил суть ошибки и как она лечится. В данном случае это скорее затычка нежели концептуально правильное исправление. Не видя описания классов целиком и пояснений, что же это такое, не могу сказать, как это делать правильно
Влад1966
0 / 0 / 0
Регистрация: 08.06.2009
Сообщений: 4
07.07.2009, 20:00  [ТС]     Как правильно инициализировать статические члены класса? #5
Спасибо Evg. Я тут порылся в книгах и на инете и нашёл ещё один вариант обьявления общих членов класса без их копирования для всех обьектов этого класса.
Итак, вариант №1 - статические члены
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
class Solution
{
    double *x;
    double y;
    static double **a = NULL;
    static int n;
public:
    static void StaticSet(int,double**)
    Solution();
    ~Solution();
    double yFunc();
}
 
void Solution::StaticSet(int numx,double **coef)
{
    n=numX;
    if(a!=NULL)
    {
        a = new double*[2];
        for(int i=0;i<2;i++) a[i] = new double[n];
        for(int i=0;i<2;i++) 
            for(int j=0;j<n;j++)
                a[i][j] = coef[i][j];
    }
}
 
Solution::Solution()
{
    x = new double[n];
    srand(time(0));
    for(int j=0;j<n;j++)
        x[j] = 2.0*(rand()/(double)RAND_MAX-0.5);
}
 
Pool::Pool(int numSols, int numX, double **coef)
{
    poolSize = numSols;
    Solution::StaticSet(numX,coef);
    for(int i=0;i<poolSize;i++)
        sols.push_back(new Solution());
}
Вариант №2 - отдельный класс-ссылка
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
class Statics
{
public:
    double **a;
    int n;
    Statics(int,double **);
    ~Statics();
};
 
class Solution
{
    double *x;
    double y;
    Statics *t
public:
    Solution(Statics *t);
    ~Solution();
    double yFunc();
}
 
Statics::Statics(int numX,double **coef)
{
    n=numX;
    a = new double*[2];
    for(int i=0;i<2;i++) a[i] = new double[n];
    for(int i=0;i<2;i++) 
        for(int j=0;j<n;j++)
                a[i][j] = coef[i][j];
}
 
Solution::Solution(Statics *in_t)
{
    t=in_t;
    srand(time(0));
    for(int j=0;j<t->n;j++)
        x[j] = 2.0*(rand()/(double)RAND_MAX-0.5);
}
 
class Pool
{
    vector<Solution> sols;
    int poolSize;
public:
    Pool(int,int,double*);
    ~Pool();
}
 
Pool::Pool(int numSols, int numX, double **coef)
{
    poolSize = numSols;
    Statics stat(numX,coef);
    for(int i=0;i<poolSize;i++)
    {
        Solution sol = new Solution (&stat);
        sols.push_back(sol);
    }
}
Какой вариант имеет больше преимуществ?
ISergey
Maniac
Эксперт С++
1372 / 883 / 52
Регистрация: 02.01.2009
Сообщений: 2,652
Записей в блоге: 1
07.07.2009, 20:11     Как правильно инициализировать статические члены класса? #6
Цитата Сообщение от Evg Посмотреть сообщение
C++
1
2
3
4
5
6
class Solution
{
 ...
 static double **a = NULL ; // <------ статически инициализируем NULL'ом
 ...
}
Вообще так надо
C++
1
2
3
4
5
6
7
class Solution
{
 ...
 static double **a; // = NULL ; // <------ статически инициализируем NULL'ом
 ...
}
double** Solution::а = NULL; // <------ статически инициализируем
Evg
Эксперт CАвтор FAQ
17469 / 5707 / 362
Регистрация: 30.03.2009
Сообщений: 15,663
Записей в блоге: 26
07.07.2009, 20:21     Как правильно инициализировать статические члены класса? #7
Цитата Сообщение от Влад1966 Посмотреть сообщение
Какой вариант имеет больше преимуществ?
Я уже писал, чтобы понять, как идеологически делать правильно, надо понять, а что ты делать будешь.

Цитата Сообщение от ISergey Посмотреть сообщение
Вообще так надо
Можно и так, но Си++ разрешает статическую инициализацию внутри класса для integral типов (т.е. целые и поинтеры). А вот плавающие уже так инициализировать нельзя. Удобнее это делать внутри класса, тогда сразу видно что к чему
ISergey
Maniac
Эксперт С++
1372 / 883 / 52
Регистрация: 02.01.2009
Сообщений: 2,652
Записей в блоге: 1
07.07.2009, 20:27     Как правильно инициализировать статические члены класса? #8
Можно и так, но Си++ разрешает статическую инициализацию внутри класса для integral типов (т.е. целые и поинтеры). А вот плавающие уже так инициализировать нельзя. Удобнее это делать внутри класса, тогда сразу видно что к чему
C++
1
2
3
4
5
6
7
8
9
10
11
class Employee{
    static int **x = 0;
public:
};
 
//int **Employee::x = 0;
 
int main()
{
    return 0;
}
1>------ Build started: Project: testing, Configuration: Debug Win32 ------
1>Compiling...
1>main.cpp
1>d:\progcode\c++\projforum\testing\main.cpp(5) : error C2864: 'Employee::x' : only static const integral data members can be initialized within a class
1>Build log was saved at "file://d:\ProgCode\C++\ProjForum\testing\Debug\BuildLog.htm"
1>testing - 1 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
Evg
Эксперт CАвтор FAQ
17469 / 5707 / 362
Регистрация: 30.03.2009
Сообщений: 15,663
Записей в блоге: 26
07.07.2009, 20:42     Как правильно инициализировать статические члены класса? #9
Ах ты ёлки зелёные, это ж только для const'ов так можно. ТОгда да, отдельной строкой
Влад1966
0 / 0 / 0
Регистрация: 08.06.2009
Сообщений: 4
07.07.2009, 21:18  [ТС]     Как правильно инициализировать статические члены класса? #10
Значит первый вариант не годится? Статические данные иницилизируются внутри класса, что запрещено если они не const. Как насчёт второго варианта с классом-ссылкой. Будет ли копироваться класс Statics для каждого обьекта класса Solution или нет? Мне нужна только одна версия Statics для 100 обьектов класса Solution.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
class Statics
{
public:
    double **a;
    int n;
    Statics(int,double **);
    ~Statics();
};
 
class Solution
{
    double *x;
    double y;
    Statics *t
public:
    Solution(Statics *t);
    ~Solution();
    double yFunc();
}
 
Statics::Statics(int numX,double **coef)
{
    n=numX;
    a = new double*[2];
    for(int i=0;i<2;i++) a[i] = new double[n];
    for(int i=0;i<2;i++) 
        for(int j=0;j<n;j++)
                a[i][j] = coef[i][j];
}
 
Solution::Solution(Statics *in_t)
{
    t=in_t;
    srand(time(0));
    for(int j=0;j<t->n;j++)
        x[j] = 2.0*(rand()/(double)RAND_MAX-0.5);
}
 
class Pool
{
    vector<Solution> sols;
    int poolSize;
public:
    Pool(int,int,double*);
    ~Pool();
}
 
Pool::Pool(int numSols, int numX, double **coef)
{
    poolSize = numSols;
    Statics stat(numX,coef);
    for(int i=0;i<poolSize;i++)
    {
        Solution sol = new Solution (&stat);
        sols.push_back(sol);
    }
}
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
07.07.2009, 21:53     Как правильно инициализировать статические члены класса?
Еще ссылки по теме:
C++ Класс MyString через статические члены класса
Конструктор класса, содержащего только статические члены C++
Как правильно инициализировать динамический массив пользовательского класса C++
класс «Строка» (данные-члены класса – строчка, функции-члены класса – операции) C++
C++ Друзья, подскажите, говорят, что можно поля класса инициализировать в момент объявления класса. Как это сделать?

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Evg
Эксперт CАвтор FAQ
17469 / 5707 / 362
Регистрация: 30.03.2009
Сообщений: 15,663
Записей в блоге: 26
07.07.2009, 21:53     Как правильно инициализировать статические члены класса? #11
Цитата Сообщение от Влад1966 Посмотреть сообщение
Значит первый вариант не годится? Статические данные иницилизируются внутри класса, что запрещено если они не const.
Годится, только его немного подправить надо. ISergey в посте 6 написал как

Цитата Сообщение от Влад1966 Посмотреть сообщение
Как насчёт второго варианта с классом-ссылкой. Будет ли копироваться класс Statics для каждого обьекта класса Solution или нет? Мне нужна только одна версия Statics для 100 обьектов класса Solution.
Второй вариант плох тем, что он будет работать только в том случае, если будет создан только один экземпляр класса Pool. Т.е. на самом деле второй вариант плохой. Да и без поллитры не сразу поймёшь, в чём дело

Первый вариант нужно будет дорабатывать на тот случай, если у класса Statics будет несколько конструкторов. В этом случае для концептуальной правильности код по выделению памяти для a надо вынести в отдельный private метод и из каждого конструктора этот метод дёргать
Yandex
Объявления
07.07.2009, 21:53     Как правильно инициализировать статические члены класса?
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru