Форум программистов, компьютерный форум, киберфорум
Наши страницы

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

Войти
Регистрация
Восстановить пароль
 
Renji
2063 / 1420 / 323
Регистрация: 05.06.2014
Сообщений: 4,081
#1

Опережающее определение констант - C++

23.05.2016, 09:22. Просмотров 92. Ответов 6
Метки нет (Все метки)

Есть класс Test, содержащий поле value являющееся указателем на Test. Есть два константных объекта Test - t1 и t2. Указатель в t1 должен указывать на t2, а указатель в t2 должен указывать на t1. Причем, прописаться эти указатели должны в конструкторах объектов. Во-первых, потому что это константы, которые иначе чем через конструктор не настроишь. Во-вторых, чтобы не вызывать руками какой ни будь initMyLib() настраивающий t1 и t2. Да вот только незадача - код вида test t1(&t2),t2(&t1) не работает, так как t2 здесь используется до своего объявления.

Я, вроде бы, нашел решение - надо t1 и t2 сделать static членами Test. Тогда декларация объектов отдельно, их инициализация отдельно. Но возник вопрос - а можно решить задачу без static?
C++
1
2
3
4
5
6
7
8
9
10
struct test
{
    test(const test*_value):value(_value){}
    const test* value;
 
    static const test t1,t2;
};
 
const test test::t1(&test::t2);
const test test::t2(&test::t1);
0
Лучшие ответы (1)
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
23.05.2016, 09:22
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Опережающее определение констант (C++):

Зачем нужно опережающее объявление класса в заголовке? - C++
Часто натыкаюсь на такой код: class NewType; class Class1 { public: Class1(); private: NewType *field; };

Отличие ввода констант - C++
Чем отличается int const i = l; // и const int m = n;

Могу ли я использовать несколько констант? - C++
Возник такой вопрос, могу ли я сразу несколько констант объявить в программе и использовать их все в одной операции ? Вот написал программу...

Перегрузка констант true и false - C++
помогите, а то не могу разобраться =(( перегрузка констант true и false: обращение к экземпляру класса дает значение true, если строка не...

Запись четырехсимвольных констант в int - C++
Вопрос состоит в следующем. Почему восьмеричные и шестнадцатиричные символьные коды четырехсимвольной константы записываются в int в...

Хранение конфигурационных целочисленных констант - C++
Как известно при написании программ с использованием системных функций очень часто приходится применять константы в качестве значений опций...

6
zss
Модератор
Эксперт С++
6634 / 6196 / 2051
Регистрация: 18.12.2011
Сообщений: 16,155
Завершенные тесты: 1
23.05.2016, 11:10 #2
Т.е. в t1 Должен быть адрес t2
а в t2 - адрес t1?
Я бы попробовал что-то типа:
C++
1
2
3
4
5
6
struct test
{
   test(const test*_value):value(_value),t1((test*)(&t2)),t2((test*)(&t1)){}
   const test* value;
   const test *t1,*t2;
};
Но, как это потом использовать, я не понимаю.
Получается противоречие. Переменная должна содержать адрес типа test, а пытаемся записать адрес переменной,
которая якобы содержит адрес типа test.

Может быть надо что-то типа:
C++
1
2
3
4
5
6
7
struct test
{
   test(const test*_value):value(_value),pt1(&t2),pt2(&t1){}
   const test* value;
   test t1,t2;
   const test *pt1,*pt2;
};
0
Pink_Pank
44 / 28 / 10
Регистрация: 04.04.2016
Сообщений: 190
23.05.2016, 11:43 #3
Чтобы получить адрес какого-то объекта (т.е. указатель на него) - объект нужно предварительно создать (чтобы было от чего получать адрес). Ваша задача не имеет решения без отдельного Init().
Либо использовать махинации с двойными указателями вида:
C++
1
2
3
4
5
6
7
8
9
10
11
struct test
{
    test(const test **value) : _value(value) {}
    const test **_value;
};
 
const test *ptrT2 = 0;
const test **pPtrT2 = &ptrT2;
const test t1(pPtrT2);
const test *ptrT1 = &t1;
const test t2(&ptrT1);
И далее где-то в коде:
C++
1
ptrT2 = &t2;
Но по-сути, это аналог того же Init() с усложнением работы с переменными класса

Да, и константы у вас сами классы, а не указатели на них. Поэтому инициализировать их можно где угодно.
0
DrOffset
7471 / 4467 / 1015
Регистрация: 30.01.2014
Сообщений: 7,321
23.05.2016, 12:07 #4
Лучший ответ Сообщение было отмечено автором темы, экспертом или модератором как ответ
Renji,
вариант 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
class Test
{
public:
    Test(Test const * v)
        : m_value(v)
    { }
 
private:
    Test const * m_value;
};
 
class Holder
{
public:
    Holder() : t1(&t2), t2(&t1)
    { }
 
private:
    Test const t1;
    Test const t2;
};
 
int main()
{
    Holder const h;
}


Вариант 2:
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Test
{
public:
    Test(Test const * v)
        : m_value(v)
    { }
 
private:
    Test const * m_value;
};
 
int main()
{
    Test const t[2] = { t + 1, t };
}
3
Pink_Pank
44 / 28 / 10
Регистрация: 04.04.2016
Сообщений: 190
23.05.2016, 12:26 #5
Даа... Я не ищу легких путей...
0
Mr.X
Эксперт С++
3053 / 1698 / 265
Регистрация: 03.05.2010
Сообщений: 3,867
23.05.2016, 13:33 #6
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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
//Есть класс Test, содержащий поле value являющееся указателем на Test.
//Есть два константных объекта Test - t1 и t2. Указатель в t1 должен
//указывать на t2, а указатель в t2 должен указывать на t1. Причем,
//прописаться эти указатели должны в конструкторах объектов. Во-первых,
//потому что это константы, которые иначе чем через конструктор не настроишь.
//Во-вторых, чтобы не вызывать руками какой ни будь initMyLib() настраивающий
//t1 и t2. Да вот только незадача - код вида test t1(&t2),t2(&t1) не работает,
//так как t2 здесь используется до своего объявления.
 
//Я, вроде бы, нашел решение - надо t1 и t2 сделать static членами Test.
//Тогда декларация объектов отдельно, их инициализация отдельно. Но возник
//вопрос - а можно решить задачу без static?
///////////////////////////////////////////////////////////////////////////////
#include <algorithm>
#include <iostream>
///////////////////////////////////////////////////////////////////////////////
struct  T
{
    //-------------------------------------------------------------------------
    const   T   *   ptr_;
    //-------------------------------------------------------------------------
    T( T    const   *   ptr     =   0 )
        :
        ptr_{ ptr }
    {}
    //-------------------------------------------------------------------------
};
///////////////////////////////////////////////////////////////////////////////
void    swap_pointers
    (
        T   const   *   const   &   ptr_A,
        T   const   *   const   &   ptr_B
    )
{
    T   *   &   ptr_AA  =   const_cast< T*& >   ( ptr_A );
    T   *   &   ptr_BB  =   const_cast< T*& >   ( ptr_B );
 
    std::swap   (
                    ptr_AA,
                    ptr_BB
                );
}
///////////////////////////////////////////////////////////////////////////////
int     main()
{
    const   T   t1;
    const   T   t2( &t1 );
    const   T   t3( &t2 );
 
    swap_pointers
        (
            t1.ptr_,
            t3.ptr_
        );
 
    std::cout   <<  "&t1 = "
                <<  &t1
                <<  std::endl
 
                <<  "&t2 = "
                <<  &t2
                <<  std::endl
 
                <<  "t1.ptr_ = "
                <<  t1.ptr_
                <<  std::endl
 
                <<  "t2.ptr_ = "
                <<  t2.ptr_
                <<  std::endl
 
                <<  "t3.ptr_ = "
                <<  t3.ptr_
                <<  std::endl;
}
0
Renji
2063 / 1420 / 323
Регистрация: 05.06.2014
Сообщений: 4,081
23.05.2016, 14:21  [ТС] #7
Цитата Сообщение от DrOffset Посмотреть сообщение
Вариант 2:
Красивое решение, спасибо.
Цитата Сообщение от Pink_Pank Посмотреть сообщение
Да, и константы у вас сами классы, а не указатели на них. Поэтому инициализировать их можно где угодно.
При желании можно, да. И вроде как той инициализации всего одна строчка. Но rand дай одну строчку, Curl дай одну строчку, Xerces дай одну строчку... И еще в памяти держи кому строчку надо, кому не надо. Такая практика малость раздражает и хочется по возможности ее избегать.
0
23.05.2016, 14:21
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
23.05.2016, 14:21
Привет! Вот еще темы с ответами:

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

Сделать массив констант, содержащий символы от '0' до '9' и от 'A' до 'Z' - C++
Как в С++ сделать массив констант, содержащий символы от 0 до 9 и от A до Z

Зачем в конце констант добавляют L либо F - C++
Столкнулся с записью вида: float i = 10000.06f зачем так делать и что оно даёт, в литературе по С++ не встречал, сейчас читаю...

Вывести слово с помощью символьных констант - C++
помогите написать программу: Вывести слово с помощью символьных констант.


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

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
Опции темы

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