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

Двухстороннее взаимодействие классов - C++

Восстановить пароль Регистрация
 
 
RAFA91
Заблокирован
30.10.2015, 15:44     Двухстороннее взаимодействие классов #1
Добрый день !

Столкнулся с такой технической проблемой.

Есть два класса А и В.

Класс B должен содержать обьект класса А , а класс А обьект класса В.

В результате компиляции получаю ошибки скорее всего из-за неправильного размещения классов.

Подскажите пожалуйста как решить эту проблему.

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
 #include <iostream>
using namespace std;
 
class B;
 
class A
{
    //B b; // ошибка
    public:
    A() {cout<<"Конструктор А"<<endl;} 
    void func_1()
    {
        cout<<"Класс А"<<endl;
    }
};
class B
{
    A a;
    public:
    B() {cout<<"Конструктор B"<<endl;} 
    void func_1()
    {
        cout<<"Класс В"<<endl;
        a.func_1();
    }
};
 
int main() 
{
    B b;
    b.func_1();
    return 0;
}
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
30.10.2015, 15:44     Двухстороннее взаимодействие классов
Посмотрите здесь:

C++ Взаимодействие Двух классов.
C++ Взаимодействие объектов разных классов
C++ Взаимодействие между объектами единой иерархии классов
Взаимодействие плагинов C++
C++ Взаимодействие VB и VC++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Renji
1535 / 983 / 240
Регистрация: 05.06.2014
Сообщений: 2,963
30.10.2015, 15:59     Двухстороннее взаимодействие классов #2
Цитата Сообщение от RAFA91 Посмотреть сообщение
Класс B должен содержать обьект класса А , а класс А обьект класса В.
Не взлетит, ибо в общем случае размер таких классов будет бесконечным.
Класс A содержит int x + класс B.
Класс B содержит int y + класс А.
Класс A содержит int x + класс B int y + класс A.
Размер класса A=Размер класса A+размер int x+размер int y
Абсурдность последнего равенства оцените сами.

Ну а решается задача через указатели:
C++
1
2
3
4
5
6
7
8
9
struct A;
struct B
{
    std::unique_ptr<A> x;
};
struct A
{
    std::unique_ptr<B> y;
};
RAFA91
Заблокирован
30.10.2015, 16:43  [ТС]     Двухстороннее взаимодействие классов #3
Цитата Сообщение от Renji Посмотреть сообщение
Ну а решается задача через указатели:

через указатели на что ?

мне нужно из класса B вызывать методы класса А и наоборот.
Renji
1535 / 983 / 240
Регистрация: 05.06.2014
Сообщений: 2,963
30.10.2015, 16:56     Двухстороннее взаимодействие классов #4
Цитата Сообщение от RAFA91 Посмотреть сообщение
через указатели на что ?
На объекты в динамической памяти, созданные через new A и new B.
Цитата Сообщение от RAFA91 Посмотреть сообщение
мне нужно из класса B вызывать методы класса А и наоборот.
Ну, если только это... Вызывать методы B из A через B_buddy()->B_method().
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
struct B;
struct A
{
    inline B*B_buddy();
};
struct B
{
    inline A*A_buddy();
};
struct AB:A,B
{
};
 
inline A*B::A_buddy(){
    return static_cast<AB*>(this);
}
inline B*A::B_buddy(){
    return static_cast<AB*>(this);
}
RAFA91
Заблокирован
30.10.2015, 17:11  [ТС]     Двухстороннее взаимодействие классов #5
не вьехал я в этот код. тут сильно много новых причиндалов из с++ 11.

как же раньше решали эту проблему ?

Добавлено через 5 минут
проблемные строки закомментировал.

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
 #include <iostream>
using namespace std;
 
class B;
 
class A
{
    //B b; 
    public:
    A() {cout<<"Конструктор А"<<endl;} 
    void func_1()
    {
        cout<<"Класс А"<<endl;
    }
    void func_2()
    {
        cout<<"Класс А"<<endl;
        //b.func_2();
    }
};
class B
{
    A a;
    public:
    B() {cout<<"Конструктор B"<<endl;} 
    void func_1()
    {
        cout<<"Класс В"<<endl;
        a.func_1();
    }
    void func_2()
    {
        cout<<"Класс В"<<endl;
    }
};
 
int main() 
{
    B b;
    b.func_1();
    return 0;
}
Kerry_Jr
Модератор
 Аватар для Kerry_Jr
1859 / 1655 / 577
Регистрация: 14.05.2014
Сообщений: 4,757
Записей в блоге: 1
Завершенные тесты: 5
30.10.2015, 17:16     Двухстороннее взаимодействие классов #6
Цитата Сообщение от RAFA91 Посмотреть сообщение
тут сильно много новых причиндалов из с++ 11.
их тут целых ни одного
Renji
1535 / 983 / 240
Регистрация: 05.06.2014
Сообщений: 2,963
30.10.2015, 17:19     Двухстороннее взаимодействие классов #7
Цитата Сообщение от RAFA91 Посмотреть сообщение
не вьехал я в этот код. тут сильно много новых причиндалов из с++ 11.
Никакого C++11, учите тему "множественное наследование". На пальцах - A и B объединяются в класс AB. Танцуя от предположения "мы лежим в AB", объект A может узнать где лежит объект B и пнуть его метод.
Kerry_Jr
Модератор
 Аватар для Kerry_Jr
1859 / 1655 / 577
Регистрация: 14.05.2014
Сообщений: 4,757
Записей в блоге: 1
Завершенные тесты: 5
30.10.2015, 17:20     Двухстороннее взаимодействие классов #8
Цитата Сообщение от RAFA91 Посмотреть сообщение
как же раньше решали эту проблему ?
правильно продумывали иерархию классов.
GbaLog-
Не Эксперт C++
1522 / 626 / 176
Регистрация: 24.08.2014
Сообщений: 2,541
Записей в блоге: 1
Завершенные тесты: 2
30.10.2015, 17:39     Двухстороннее взаимодействие классов #9
RAFA91, Избежать перевключения файлов
RAFA91
Заблокирован
30.10.2015, 17:51  [ТС]     Двухстороннее взаимодействие классов #10
Цитата Сообщение от Renji Посмотреть сообщение
Никакого C++11
а к чиму тогда эти умные указатели ? про создание третьего класса думал (но без наследований) - но с таким же успехом я могу

обойтись одним мейном.

странно что вы мне не намекнули запихнуть класс А к примеру в класс В
Renji
1535 / 983 / 240
Регистрация: 05.06.2014
Сообщений: 2,963
30.10.2015, 17:53     Двухстороннее взаимодействие классов #11
Сообщение было отмечено автором темы, экспертом или модератором как ответ
Цитата Сообщение от RAFA91 Посмотреть сообщение
а к чиму тогда эти умные указатели ?
К автоматической очистке памяти, причем в другом примере. Умные указатели, кстати, и в C++ были, просто назывались auto_ptr.
RAFA91
Заблокирован
30.10.2015, 18:04  [ТС]     Двухстороннее взаимодействие классов #12
на данном этапе решения проблемы предположим что обьекты хранятся в стеке или мы сами в состоянии освободить память.

тоесть идея решения заключается в создании класса ниже по иерархии ?
Melg
416 / 152 / 62
Регистрация: 23.09.2013
Сообщений: 306
30.10.2015, 18:19     Двухстороннее взаимодействие классов #13
Сообщение было отмечено автором темы, экспертом или модератором как ответ
RAFA91, может быть данное решение Вам подойдет?

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
#include <iostream>
 
using std::cout;
using std::endl;
 
class B;
 
class A {
  B* b_;
 
 public:
  A(B* b) : b_(b) { cout << "Конструктор А" << endl; }
  void func_1();
  void func_2() { cout << "Класс A func_2" << endl; }
};
 
class B {
  A a;
 
 public:
  B() : a(this) { cout << "Конструктор B" << endl; }
 
  void func_1() {
    cout << "Класс В func_1" << endl;
    a.func_1();
  }
 
  void func_2() {
    cout << "Класс В func_2" << endl;
    a.func_2();
  }
};
 
void A::func_1() {
  cout << "Класс А func_1" << endl;
  b_->func_2();
}
 
int main() {
  B b;
  b.func_1();
}
Пруф работоспособности:
http://ideone.com/3EHrZe

Добавлено через 39 секунд
В общем случае стоит избегать двойных связей между классами, и превращать их в односторонние - это улучшит архитектуру приложения за счет снижения зависимости между классами.
RAFA91
Заблокирован
31.10.2015, 14:45  [ТС]     Двухстороннее взаимодействие классов #14
Цитата Сообщение от Melg Посмотреть сообщение
B() : a(this) { cout << "Конструктор B" << endl; }
не совсем понял эту конструкцию.

или это равносильно

A a(зис); ?
Melg
416 / 152 / 62
Регистрация: 23.09.2013
Сообщений: 306
31.10.2015, 16:02     Двухстороннее взаимодействие классов #15
RAFA91, я использовал список инициализации конструктора класса B, в котором вызвал конструктор класса A, для поля класса a передав в него указатель на класс B. В данном случае - указатель на себя.
Подробнее про список инициализации конструктора можно почитать по ссылке:
http://www.learncpp.com/cpp-tutorial...ization-lists/

Добавлено через 1 минуту
Краткий ответ: с точки зрения класса A - да, равносильно. За исключением того факта, что время жизни поля a привязано к времени жизни объекта типа B. А вызов A a(this); - в любой области видимости, меньшей чем класс, заставил бы объект А разрушиться раньше.
RAFA91
Заблокирован
31.10.2015, 16:14  [ТС]     Двухстороннее взаимодействие классов #16
немного поколдовал и пришел к такому решению.

для обмена данными м-ду классами есть два метода transmitter() и receiver()

обьекты создаются в главной функции.

можно ли применять подобный подход или есть более элегантное решение ?

как вообще в жизни делается взаимодействие классов (общение)?

классов взаимодействия может быть много.

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
#include <iostream>
using namespace std;
 
class A
{
    int x;
    int y; //переменная которая будет передана
    int z; //переменная которая была принята
    public:
    A(int a) : x(a),y(0),z(0) {}
    void show() const 
    {
        cout<<"x = "<<x<<" y = "<<y<<" z = "<<z<<endl;
    }
    int transmitter() const {return y;}
    void receiver(int a) {z=a;}
    void calculation() {y=x+z; x += z;}
};
 
class B
{
    int x;
    int y; //переменная которая будет передана
    int z; //переменная которая была принята
    public:
    B(int a) : x(a),y(0),z(0) {}
    void show() const 
    {
        cout<<"x = "<<x<<" y = "<<y<<" z = "<<z<<endl;
    }
    int transmitter() const {return y;}
    void receiver(int a) {z=a;}
    void calculation() {y=x+z; x += z;}
};
 
int main() 
{
    A a(28);
    B b(34);
    a.calculation();
    b.calculation();
    a.show();
    b.show();
    //передача информации от А к В
    b.receiver(a.transmitter());
    //передача информации от B к A
    a.receiver(b.transmitter());
    cout<<"*************************"<<endl;
    a.show();
    b.show();
    
    
    return 0;
}
Melg
416 / 152 / 62
Регистрация: 23.09.2013
Сообщений: 306
31.10.2015, 16:33     Двухстороннее взаимодействие классов #17
Сообщение было отмечено автором темы, экспертом или модератором как ответ
RAFA91, В Вашем случае два класса полностью повторяют функциональность, поэтому можно избавиться от дублирования кода, оставив один класс. Кроме того, названия некоторых Ваших функций и переменных не соответствуют их реальному смысловому значению, поэтому их следует переименовать, для уменьшения семантического шума от Вашего кода. Пример слегка отредактированной версии:
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
#include <iostream>
#include <string>
 
using std::cout;
using std::endl;
 
class A {
 public:
  A(int x) : x_(x) {}
 
  int y() const { return y_; }
 
  void set_z(int z) { z_ = z; }
 
  void show() const {
    cout << "x = " << x_ << " y = " << y_ << " z = " << z_ << endl;
  }
 
  void calculation() {
    y_ = x_ + z_;
    x_ += z_;
  }
 
 private:
  int x_ = 0;
  int y_ = 0;
  int z_ = 0;
};
 
void ShowSeparator() { cout << "*************************" << endl; }
 
int main() {
  A a(28);
  A b(34);
  a.calculation();
  b.calculation();
  a.show();
  b.show();
  //передача информации от А к В
  b.set_z(a.y());
  //передача информации от B к A
  a.set_z(b.y());
  ShowSeparator();
  a.show();
  b.show();
}
Пруф работоспособности:
http://ideone.com/z4V1Lv

Отвечая на Ваш вопрос: если Вам необходимо передавать исключительно данные, без поведения - тогда передача в качестве возвращаемых значений и аргументов функций вполне приемлема. В данном случае вы отделяете код непосредственной логики выполнения (инкапсулируете его в классе), от более высокоуровневой логики, за которую в Вашем случае отвечает функция main. В более сложных ситуациях, когда, например, требуется изменять поведение в процессе работы - используют связку - наследование + виртуальные функции, что дает возможность передавая указатель на базовый (часто абстрактный) класс - в класс - приемник - получать разное поведение приемника, в зависимости от того, какая конкретная реализация базового класса была передана.
RAFA91
Заблокирован
31.10.2015, 17:34  [ТС]     Двухстороннее взаимодействие классов #18
Цитата Сообщение от Melg Посмотреть сообщение
int x_ = 0;
* int y_ = 0;
* int z_ = 0;
а разве так можно ?

в реале классы А и B отличаются методами которые я не все изложил.

я только привел функции обмена данными для простоты.

как же это привязать к более адекватному подходу общения классов?
Renji
1535 / 983 / 240
Регистрация: 05.06.2014
Сообщений: 2,963
01.11.2015, 04:52     Двухстороннее взаимодействие классов #19
Цитата Сообщение от RAFA91 Посмотреть сообщение
а разве так можно ?
В C++11 - да.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
02.11.2015, 15:28     Двухстороннее взаимодействие классов
Еще ссылки по теме:

C++ Взаимодействие классов
C++ Как реализовать взаимодействие классов в игре "Змейка"
Взаимодействие классов C++

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

Или воспользуйтесь поиском по форуму:
RAFA91
Заблокирован
02.11.2015, 15:28  [ТС]     Двухстороннее взаимодействие классов #20
Добрый день !
Решил для двухстороннего взаимодействия классов B and C воспользоваться полиморфизмом.
Цель - иметь возможность в одном классе просматривать данные другого класса.
Можно ли применять такой подход взаимодействия классов ?

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
#include <iostream>
using namespace std;
 
class A
{
    protected:
    int x,y,z;
    public:
    A(int a) : x(a),y(a*a),z(a*a*a) {cout<<"Конструктор А "<<this<<endl;}
    virtual ~A() {cout<<"Деструктор А "<<this<<endl;}
    virtual void func_1(A *) const =0 ;
    virtual void func_2() const =0 ;
    int get_x() const {return x;}
    int get_y() const {return y;}
    int get_z() const {return z;}
};
 
class B : public A
{
    public:
    B(int a) : A(a) {cout<<"Конструктор B "<<this<<endl;}
    ~B() {cout<<"Деструктор B "<<this<<endl;}
    void func_1(A *b) const
    {
        cout<<"Данные класса C: ";
        cout<<"x = "<<b->get_x();
        cout<<" y = "<<b->get_y();
        cout<<" z = "<<b->get_z()<<endl;
        b->func_2();
    }
    void func_2() const{cout<<"Класс B x = "<<x
    <<" y = "<<y<<" z = "<<z<<endl;}
};
 
class C : public A
{
    public:
    C(int a) : A(a) {cout<<"Конструктор C "<<this<<endl;}
    ~C() {cout<<"Деструктор C "<<this<<endl;}
    void func_1(A *c) const
    {
        cout<<"Данные класса B: ";
        cout<<"x = "<<c->get_x();
        cout<<" y = "<<c->get_y();
        cout<<" z = "<<c->get_z()<<endl;
        c->func_2();
    }
    void func_2() const{cout<<"Класс C x = "<<x
    <<" y = "<<y<<" z = "<<z<<endl;}
};
 
int main() 
{
    A *c = new C(56);
    A *b = new B(45);
    c->func_1(b);
    b->func_1(c);
    cout<<"***************************"<<endl;
 
 
    return 0;
}
http://ideone.com/zkCdR9
Yandex
Объявления
02.11.2015, 15:28     Двухстороннее взаимодействие классов
Ответ Создать тему
Опции темы

Текущее время: 20:16. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru