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

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

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

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

07.07.2009, 04:10. Просмотров 3797. Ответов 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++
Помогите пожалуйста....я не знаю как вывести в статическое поле значения((( #include &lt;conio.h&gt; #include &lt;stdlib.h&gt; #include...

Как инициализировать члены класса, являющегося параметром шаблона - C++
#include &lt;iostream&gt; #include &lt;conio.h&gt; using namespace std; template &lt;typename SomeClass&gt; class Array { private : ...

Как правильно инициализировать данные-члены строкового типа в реализации функции-члена? - C++
Всем здравствуйте. У меня тут возникла очень глупая ошибка и я не могу понять в чем причина и как ее исправить. Значит, имеется структура. ...

Статические члены класса - C++
Добрый день. Проходили тему - статические члены класса. Написали программу, вылезает ошибка, помогите побороть пожалуйста. #include...

Статические члены класса - C++
Доброго времени суток. Задача состоит в том, чтобы создать список обыектов класса Test, с возможностью последующего добавления элементов...

Статические массивы, члены класса - C++
необходимо создать статический массив. компилятор gcc #include&lt;iostream&gt; class c{ public: static const char x = &quot;qwe&quot;; ...

Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Alexiski
Любитель давать советы
339 / 131 / 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
17634 / 5858 / 378
Регистрация: 30.03.2009
Сообщений: 16,160
Записей в блоге: 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
Эксперт С++
1373 / 884 / 52
Регистрация: 02.01.2009
Сообщений: 2,653
Записей в блоге: 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
17634 / 5858 / 378
Регистрация: 30.03.2009
Сообщений: 16,160
Записей в блоге: 26
07.07.2009, 20:21 #7
Цитата Сообщение от Влад1966 Посмотреть сообщение
Какой вариант имеет больше преимуществ?
Я уже писал, чтобы понять, как идеологически делать правильно, надо понять, а что ты делать будешь.

Цитата Сообщение от ISergey Посмотреть сообщение
Вообще так надо
Можно и так, но Си++ разрешает статическую инициализацию внутри класса для integral типов (т.е. целые и поинтеры). А вот плавающие уже так инициализировать нельзя. Удобнее это делать внутри класса, тогда сразу видно что к чему
ISergey
Maniac
Эксперт С++
1373 / 884 / 52
Регистрация: 02.01.2009
Сообщений: 2,653
Записей в блоге: 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
17634 / 5858 / 378
Регистрация: 30.03.2009
Сообщений: 16,160
Записей в блоге: 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);
    }
}
Evg
Эксперт CАвтор FAQ
17634 / 5858 / 378
Регистрация: 30.03.2009
Сообщений: 16,160
Записей в блоге: 26
07.07.2009, 21:53 #11
Цитата Сообщение от Влад1966 Посмотреть сообщение
Значит первый вариант не годится? Статические данные иницилизируются внутри класса, что запрещено если они не const.
Годится, только его немного подправить надо. ISergey в посте 6 написал как

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

Первый вариант нужно будет дорабатывать на тот случай, если у класса Statics будет несколько конструкторов. В этом случае для концептуальной правильности код по выделению памяти для a надо вынести в отдельный private метод и из каждого конструктора этот метод дёргать
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
07.07.2009, 21:53
Привет! Вот еще темы с ответами:

Где инициализировать члены класса CTreeCtrl? - C++
В диалоговом окне, например, оконные члены класса инициализируются в OnInitDialog(). Мне нужно получить буквы всех дисков, которые уже...

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

Конструктор класса, содержащего только статические члены - C++
Практикуюсь по книге Стенли Липпмана &quot;Язык программирования C++ вводный курс&quot; 4 изд. Осваиваю главу 12.6 Статические члены класса. В...

Как правильно инициализировать динамический массив пользовательского класса - C++
Допустим есть класс: class A { public: A(); A(int a, int b, int c) {} }; и нам нужно инициализировать динамический...


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

Или воспользуйтесь поиском по форуму:
Yandex
Объявления
07.07.2009, 21:53
Ответ Создать тему
Опции темы

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