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

Реализация отношения классов типа двунаправленная ассоциация, UML, порядок объявления классов, неполный класс - C++

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 10, средняя оценка - 4.90
rcyn
13 / 9 / 2
Регистрация: 30.01.2014
Сообщений: 47
06.02.2014, 01:23     Реализация отношения классов типа двунаправленная ассоциация, UML, порядок объявления классов, неполный класс #1
Доброго времени суток!
Осваивая UML, решил реализовать отношение двунаправленной ассоциации по диаграмме:
Реализация отношения классов типа двунаправленная ассоциация, UML, порядок объявления классов, неполный класс
У одного владельца (Person) может быть 0...* машин (Car).
У одной машины может быть 0...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
class Car;
 
class Person {
    vector<Car*> cars;
    string name;
public:
    string get_name() const { return name; }
    void add_car(Car* car) { 
        cars.push_back(car); 
        car->set_owner(this); 
    }
    void delete_car(Car* car) {
        for(vector<Car*>::iterator it=cars.begin(); it!=cars.end(); it++)
            if(*car == *(*it)) { 
                car->set_owner(0); 
                cars.erase(it); 
                return; 
            }
    }
};
 
class Car {
    Person* owner;
public:
    Car() : owner(0) {}
    Car(Person* person, string model = "n/a", string number = "n/a")
        :   owner(person), mod(model), num(number)
    {}
 
    Person get_owner() const { return *owner; }
    void set_owner(Person* person) { owner = person; }
 
    bool operator==(const Car& arg) {
        return ((this->mod == arg.mod)&&(this->num == arg.num));
    }
    bool operator!=(const Car& arg) {return !(*this==arg);}
    
    string mod;
    string num;
};
main():
C++
1
2
3
4
5
6
7
8
    Car* Ferrari = new Car(0,"Ferrari","LOV3K5U");
    Car* Mers = new Car(0,"Mers","C++student");
    
    Person* Dude = new Person("Jeff Lebowski");
    Dude->add_car(Ferrari);
    Dude->add_car(Mers);
    
    cout << Ferrari->get_owner()->get_name();
Вывод:
1>code.cpp(100): error C2027: использование неопределенного типа "Car"
1> code.cpp(91): см. объявление "Car"
1>code.cpp(100): error C2227: выражение слева от "->set_owner" должно указывать на тип класса, структуры или объединения либо на универсальный тип
1>code.cpp(104): error C2676: бинарный "==": "Car" не определяет этот оператор или преобразование к типу приемлемо к встроенному оператору
1>code.cpp(105): error C2027: использование неопределенного типа "Car"
1> code.cpp(91): см. объявление "Car"
1>code.cpp(105): error C2227: выражение слева от "->set_owner" должно указывать на тип класса, структуры или объединения либо на универсальный тип

Если поменять порядок объявления классов, то программа компилируется:

C++
1
2
3
4
5
6
7
8
9
10
11
12
class Person;
 
class Car {
    Person* owner;
        // . . . 
};
 
class Person {
    vector<Car*> cars;
    string name;
    // . . .
};
Я хотел спросить почему первый вариант не работает и как лучше реализовывать подобные отношения классов.
Спасибо!
Лучшие ответы (1)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
06.02.2014, 01:23     Реализация отношения классов типа двунаправленная ассоциация, UML, порядок объявления классов, неполный класс
Посмотрите здесь:

Реализация программы с помощью классов C++
C++ Объявления классов
Реализация собственных классов C++
C++ Реализация классов
C++ Реализация классов чисел
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
rcyn
13 / 9 / 2
Регистрация: 30.01.2014
Сообщений: 47
06.02.2014, 01:30  [ТС]     Реализация отношения классов типа двунаправленная ассоциация, UML, порядок объявления классов, неполный класс #2
Забыл: компилятор MS Visual Studio Express 2010
DrOffset
6420 / 3794 / 877
Регистрация: 30.01.2014
Сообщений: 6,584
06.02.2014, 01:36     Реализация отношения классов типа двунаправленная ассоциация, UML, порядок объявления классов, неполный класс #3
Цитата Сообщение от rcyn Посмотреть сообщение
Я хотел спросить почему первый вариант не работает и как лучше реализовывать подобные отношения классов.
Спасибо!
В Person у тебя идет обращение к методу класса Car - set_owner. Такое обращение требует полного определения класса, поэтому и не компилируется. Чтобы решить проблему нужно вынести реализацию методов add_car и delete_car в место где полное определение доступно. Если делать с разбиением на h и cpp файлы, то проблема решается сама собой:
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
// A.h
class B;
 
class A
{
public:
    void use_of_b();
 
private:
    B * data;
};
 
// B.h
class A;
 
class B
{
public:
    void use_of_a();
 
private:
    A * data;
};
 
// A.cpp
 
#include <A.h>
#include <B.h>
 
void A::use_of_b()
{
    //usage
}
 
//B.cpp
 
#include <B.h>
#include <A.h>
 
void B::use_of_a()
{
    //usage
}
rcyn
13 / 9 / 2
Регистрация: 30.01.2014
Сообщений: 47
06.02.2014, 01:41  [ТС]     Реализация отношения классов типа двунаправленная ассоциация, UML, порядок объявления классов, неполный класс #4
А какой механизм/принцип/правило обуславливает этот запрет?
Или просто нельзя и всё?
DrOffset
6420 / 3794 / 877
Регистрация: 30.01.2014
Сообщений: 6,584
06.02.2014, 02:24     Реализация отношения классов типа двунаправленная ассоциация, UML, порядок объявления классов, неполный класс #5
Сообщение было отмечено автором темы, экспертом или модератором как ответ
Цитата Сообщение от rcyn Посмотреть сообщение
А какой механизм/принцип/правило обуславливает этот запрет?
Или просто нельзя и всё?
Это все есть в стандарте С++. Ну и логически тут все обосновано: вот представь: нужно вызвать некий метод у класса A, а тебе доступно только имя класса. Как по-твоему компилятор должен догадаться о сигнатуре этого метода, о том, есть ли вообще такой метод в этом классе, если нет самого определения класса?
Есть языки, которые это позволяют, скажем многие динамические языки это умеют, потому что вся информация уже загружена.
С++ статически типизированный язык и проектировался так, чтобы исключить лишние проходы компилятора по коду во время разбора исходника. Поэтому и нельзя.
Yandex
Объявления
06.02.2014, 02:24     Реализация отношения классов типа двунаправленная ассоциация, UML, порядок объявления классов, неполный класс
Ответ Создать тему
Опции темы

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