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

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

Войти
Регистрация
Восстановить пароль
 
JonyCage
0 / 0 / 0
Регистрация: 18.08.2016
Сообщений: 6
Завершенные тесты: 1
#1

Скопировать объект, на который ссылается указатель на абстрактный класс - C++

17.09.2016, 19:15. Просмотров 443. Ответов 7
Метки нет (Все метки)

Доброго времени суток. У меня такое задание: написать программу символьного дифференцирования, т.е. пользователь пишет функцию f(x), а программа выводит ее производную как f'(x). Так вот есть базовый абстрактный класс, который дан в условии задачи
C++
1
2
3
4
5
6
7
class Expression
{
public:
    
    virtual Expression *diff()=0; //функция дифференцирования
    virtual void print()=0;          //функция вывода выражения
};
а проблема сейчас стоит в том, как вычислять производную произведения.
В условии выражение задается так:
C++
1
Expression *e=new Add(new Variable('x'), new Number(4));//Add это класс-сумма
Add, Variable, Number унаследованы от Expression, и я так понимаю, что в конструктор Add передаются указатели на базовый класс(что в общем-то логично) значит и в класс Mul(произведение) тоже должны передаваться указатели на базовый класс.
Я думал реализовать его примерно так,
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
class Mul: public Expression
{
private:
    Expression *ex1, *ex2   //выражения-множители
        , *ex3, *ex4        //не продиффмринцированные множители    
    ;
    bool prodif;
public:
    Mul(){}
    Mul(Expression *expr1, Expression *expr2):ex1(expr1), ex2(expr2), prodif(false){}
 
    Expression *diff()
    {
        //в ex3 как-то cкопировать значение ex1
        ex1->diff();//потом продифференцировать ex1
 
        //в ex4 как-то cкопировать значение ex2
        ex2->diff();//потом продифференцировать ex2
        prodif=true;
        return this;
    }
 
    void print()
    {
        if(!prodif)
        {
            ex1->print();
            std::cout<<'*';
            ex2->print();
        }else
        {
            std::cout<<'(';
            
            ex1->print();   //производная первого
            std::cout<<'*';
            ex4->print();   //второе без изменения
 
            std::cout<<'+';
 
            ex3->print();   //первое без изменения
            std::cout<<'*';
            ex2->print();   //производная второго
 
            std::cout<<')';
 
        }
    }
 
};
но как все таки "в ex3 как-то cкопировать значение ex1" ведь нет смысла в "ex3=ex1", а через new нельзя так как это указатели на абстрактный класс, ну или как по другому реализовать метод diff() ? Заранее благодарен.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
17.09.2016, 19:15
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Скопировать объект, на который ссылается указатель на абстрактный класс (C++):

Создать абстрактный тип данных - класс вектор, который имеет указатель на long, число элементов и переменную состояния - C++
Помогите пожалуйста, нужно написать код на с++ Создать абстрактный тип данных - класс вектор, который имеет указатель на long, число...

Получить адрес памяти, на который ссылается указатель - C++
Изучаю указатели, появился такой вопрос: int *b = new int(5); Как получить адрес памяти, на который ссылается указатель b? То есть...

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

Как проверить на какой класс ссылается указатель? - C++
То есть допустим есть базовый класс class A и производные class B:public A; class C:public A; также есть ссылка A *s; ...

Указатель на бызовый абстрактный класс. - C++
Правильно ли у меня написан &quot;умный&quot; указатель? Напонятно, как можно с помощью указателя на базовый класс вызывать методы производных...

Указатель на абстрактный шаблонный класс - C++
Есть абстрактный шаблон класса и 3 производных от него шаблонов классов. Так же есть шаблонная функция, в которую нужно передать указатель...

7
Nick Alte
Эксперт С++
1642 / 1014 / 119
Регистрация: 27.09.2009
Сообщений: 1,945
Завершенные тесты: 1
18.09.2016, 14:47 #2
Почему бы не добавить функцию
Код
virtual Expression* clone() const = 0;
в Expression, реализовав её у потомков, которые уж точно знают, как себя копировать?
1
JonyCage
0 / 0 / 0
Регистрация: 18.08.2016
Сообщений: 6
Завершенные тесты: 1
18.09.2016, 15:51  [ТС] #3
А не подскажите как тогда реализовать эту функцию
Код
virtual Expression* clone() const = 0;
к примеру у класса Add(сумма):
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
class Add:public Expression
{
private:
    Expression *expr1, *expr2; 
    
    Expression *result;
    int version;
public:
    
        //конструкторы
        Add(){}
         
    Add(Expression *s1, Expression *s2):expr1(s1), expr2(s2)
    {
        result=NULL;
    }
 
    ~Add(){delete result;}
 
    Expression *diff()
    {
        std::cout<<"add diff\n";
        result=new Add(expr1->diff(),expr2->diff());
        return result;
    }
 
    void print()
    {
        
        std::cout<<'(';
        
        expr1->print();
        std::cout<<'+';
    
        expr2->print();
        std::cout<<')';
    }
 
    Expression* clone() const
    {
        Add *add_clone=new Add(expr1, expr2);
        return add_clone;
    }
};
Мой вариант реализации ведь не создаст физической копии, точнее копия будет, но указатели expr1 и expr2 у клона будут ссылаться на те же объекты что и указатели expr1 и expr2 у оригинала, а это не имеет особого смысла. Спасибо.
0
Nick Alte
Эксперт С++
1642 / 1014 / 119
Регистрация: 27.09.2009
Сообщений: 1,945
Завершенные тесты: 1
19.09.2016, 19:30 #4
Очевидно, что для слагаемых тоже надо создать копии. Они это умеют:
C++
1
2
3
4
Expression* Add::clone() const 
{
    return new Add(expression1->clone(), expression2->clone());
}
1
JonyCage
0 / 0 / 0
Регистрация: 18.08.2016
Сообщений: 6
Завершенные тесты: 1
20.09.2016, 16:44  [ТС] #5
Спасибо за помощь, но хотелось бы еще одно уточнение по поводу освобождения выделенной памяти. Теперь у меня есть все необходимые классы, для которых программа работает корректно. Но когда я освобождаю память :

C++
1
2
3
Expression *e=new Number(4);
 
delete e;
все упирается в деструктор Number. Я описал виртуальный деструктор у класса Expression, и он вызывает деструкторы всех объектов, указанных в "выражении". Но вот вопрос : как должен выглядеть деструктор класса Number, чтобы освобождать выделенную под его объекты память. Я же использую указатель на объект, и выделяю для него память. Или же деструктор по умолчанию справится с этой задачей. Хотелось бы прояснить этот механизм. Вот класс:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Number:public Expression
{
private:
    float n;
public:
    Number (float nn):n(nn){}
    ~Number(){std::cout<<"num des\n";}
 
    Expression *diff(){return new Number(0);} 
 
    Expression *clone(){return new Number(n);}
 
    void print(){std::cout<<n;}
 
};
Благодарю.
0
Nick Alte
Эксперт С++
1642 / 1014 / 119
Регистрация: 27.09.2009
Сообщений: 1,945
Завершенные тесты: 1
20.09.2016, 19:08 #6
Деструктор отвечает за уничтожение членов класса, не могущих уничтожить себя самостоятельно. В случае Number деструктору ничего делать не надо, в случае Add следует вызвать delete для членов expr1, expr2 и result.
Чтобы это всё работало правильно, деструктор непременно должен быть виртуальным (достаточно объявить его как virtual в классе Expression).
0
JonyCage
0 / 0 / 0
Регистрация: 18.08.2016
Сообщений: 6
Завершенные тесты: 1
20.09.2016, 19:29  [ТС] #7
то есть, выделенная под Number память удалится в строке
C++
1
 delete e;
?
0
Nick Alte
Эксперт С++
1642 / 1014 / 119
Регистрация: 27.09.2009
Сообщений: 1,945
Завершенные тесты: 1
21.09.2016, 21:20 #8
Да, сначала отработает деструктор Number (он хоть и пустой, но всё же виртуальный, так что в ноль его не заоптимизируют), а потом будет удалена выделенная под объект память.
0
21.09.2016, 21:20
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
21.09.2016, 21:20
Привет! Вот еще темы с ответами:

Что такое указатель на абстрактный класс? - C++
В задании сказано - Методы класса должны принимать указатель на абстрактный класс , что это значит и как это реализовывается?

Создание объекта через указатель на базовый абстрактный класс - C++
Есть абстрактный класс, от него наследуется 3 класса. В программе предусмотрено создание нового объекта(добавление клиента страховой...

Создать абстрактный тип данных (структура) - вектор, который имеет указатель на short и число элементов - C++
Создать абстрактный тип данных (структура) - вектор, который имеет указатель на short и число элементов. Определить функции: инициализации,...

Создать абстрактный тип данных (структура) — вектор, который имеет указатель на int и число элементов - C++
Создать абстрактный тип данных (структура) - вектор, который имеет указатель на int и число элементов. Определить функции: инициализации,...


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

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

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