Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.59/29: Рейтинг темы: голосов - 29, средняя оценка - 4.59
1 / 1 / 0
Регистрация: 13.07.2015
Сообщений: 21
1

Напишите шаблонную функцию, которая по двум однотипным указателям проверяет, указывают ли они на один объект

20.02.2018, 15:29. Показов 5584. Ответов 15
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Вот задание: Предположим, что вам даётся два указателя на объект некоторого сложного полиморфного класса, который использует множественное наследование. Оба указателя имеют один и тот же тип, но могут ссылаться на разные однотипные базы внутри одного объекта.

Напишите шаблонную функцию, которая по двум однотипным указателям проверяет, указывают ли они на один объект.

C++
1
2
3
4
5
6
// возвращает true, если p и q указывают на один и тот же объект
template<class T>
bool isSameObject(T const * p, T const * q)
{
 
}
Вот мое решение:
C++
1
2
3
4
5
6
7
8
// возвращает true, если p и q указывают на один и тот же объект
template<class T>
bool isSameObject(T const * p, T const * q)
{
    if (dynamic_cast<const T *>(p) == dynamic_cast<const T *>(q))
        return true;
    else return false;
}
Я не понимаю, почему решение не проходит. И в чем ошибка?
https://stepik.org/lesson/53367/step/7?unit=31461
1
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
20.02.2018, 15:29
Ответы с готовыми решениями:

Напишите функцию, которая проверяет матрицу на симметричность.
Напишите функцию issymm (a) matlab которая берет матрицу а и возвращает число s если а является...

Напишите функцию, которая проверяет, отсортирован ли массив
Напишите функцию, которая проверяет, отсортирован ли массив вещественных чисел по невозрастанию....

Напишите функцию, которая проверяет, отсортирован ли массив вещественных чисел
4. Напишите функцию, которая проверяет, отсортирован ли массив вещественных чисел по неубыванию....

Напишите, пожалуйста, функцию в Homelisp, которая проверяет принадлежность элемента к списку
Напишите, пожалуйста, функцию в Homelisp, которая проверяет принадлежность элемента к списку. Но...

15
184 / 192 / 48
Регистрация: 25.08.2011
Сообщений: 792
20.02.2018, 18:07 2
а зачем вам dynamic_cast? Если указатели равны то указывают в одно место

с другой стороны если вам надо знать конкретный тип тут надо уже RTTI юзать
2
Комп_Оратор)
Эксперт по математике/физике
8949 / 4703 / 629
Регистрация: 04.12.2011
Сообщений: 13,999
Записей в блоге: 16
20.02.2018, 22:36 3
Лучший ответ Сообщение было отмечено zombiebober как решение

Решение

zombiebober, как мне кажется тут может быть тонкость. То есть, не все равные указатели указывают на один и тот же объект. Это потому, что если указатель равен nullptr, то он вообще никуда не указывает. Следовательно, пара таких указателей хоть и равны но не могут быть решением в ряде случаев. Возможно Ваш преподаватель имеет, это ввиду.
C++
1
2
3
4
5
6
7
template<class T>
bool isSameObject(T const * p, T const * q)
{
bool ret_bool=false;
if(p == q) ret_bool = (p == nullptr) ? false : true;
return ret_bool;
}
или что-то в этом роде.
1
73 / 69 / 38
Регистрация: 09.10.2012
Сообщений: 238
20.02.2018, 22:51 4
Может немного не по теме, но представим, что шаблонная функция принимает ссылки, а не указатели. Как будет выглядеть решение? (тут есть небольшой подвох)
0
Комп_Оратор)
Эксперт по математике/физике
8949 / 4703 / 629
Регистрация: 04.12.2011
Сообщений: 13,999
Записей в блоге: 16
20.02.2018, 23:07 5
Цитата Сообщение от IGPIGP Посмотреть сообщение
что-то в этом роде
Можно ещё вот так бы заимпрувить:

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
#include <iostream>
using namespace std;
 
template <class T> struct pointers_compire {
T * rhs,  * lhs;
enum what {none, equal, nonequal};
pointers_compire(T  * rhs_, T  * lhs_):rhs(rhs_), lhs(lhs_)
{}
what compare_what(){
what w = none;
if(rhs == nullptr || lhs == nullptr) return w;
w = rhs == lhs ? equal : nonequal;
return w;
}
void prn_what(){
what w = compare_what();
switch(w){
case equal : cout << "equal" ; break ;
case nonequal : cout << "nonequal" ; break ;
default :  cout << "none" ; break ;
}
cout << endl;
}
};
 
 
int main(int argc, char* argv[])
{
int *a, *b;
a=b=nullptr;
 
pointers_compire<int> pc0(a, b);
pc0.prn_what();
 
int c, d;
a = &c ; b = &d;
 
pointers_compire<int> pc1(a, b);
pc1.prn_what();
 
a=b;
 
pointers_compire<int> pc2(a, b);
pc2.prn_what();
 
system("pause");
return 0;
}
В том смысле, что то что имеет три логических конечных состояния, трудно свести к двум без скрытой неопределённости. Но опять же, это зависит от конкретной постановки, нужно ли вот прям уж так уж.
0
Любитель чаепитий
3742 / 1798 / 566
Регистрация: 24.08.2014
Сообщений: 6,016
Записей в блоге: 1
21.02.2018, 10:51 6
Лучший ответ Сообщение было отмечено zombiebober как решение

Решение

Цитата Сообщение от zombiebober Посмотреть сообщение
Вот мое решение
зачем вы dynamic_cast сюда приплели?
C++
1
2
3
4
5
template<typename T>
bool isEqualObjects(const T * const lhs, const T * const rhs)
{
    return lhs == rhs && lhs;
}
Цитата Сообщение от zombiebober Посмотреть сообщение
https://stepik.org/lesson/53367/step/7?unit=31461
ссылка не юзабельна.
Цитата Сообщение от mishelle92 Посмотреть сообщение
Как будет выглядеть решение?
C++
1
2
3
4
bool isEqualObjects(const T & lhs, const T & rhs)
{
    return std::addressof(lhs) == std::addressof(rhs) && std::addressof(lhs);
}
0
2376 / 834 / 317
Регистрация: 10.02.2018
Сообщений: 1,968
21.02.2018, 11:22 7
GbaLog-, не работает)
По-моему, вы как-то упустили про полиморфизм, а котором говорится у ТС.
В принципе, динамик каст поддерживает полиморфизм, но нужно тогда как-то знать конечный класс.
Я не знаю, как это делать. TC ссылается на какой-то видео ролик про 11 и 14 стандарты, может там что-то подходящее есть.
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
#include <iostream>
#include <typeinfo>
 
class A {};
class B : public A {};
class C : public A {};
class D : public A, B, C {};
 
//  A    A
//  |    |
//  B    C    A
//  |    |    |
//  +----+----+
//  |
//  D
 
template<typename T>
bool isEqualObjects(const T * const lhs, const T * const rhs)
{
    return lhs == rhs && lhs;
}
 
int main()
{
    D d;
    A* d1 = &d;
    A* d2 = (C*)&d;
    A* d3 = (B*)&d;
 
    std::cout << "isEqualObjects(d1, d2) return " << isEqualObjects(d1, d2) << std::endl;
 
    //std::cout << "d ptr: " << &d << " type: " << typeid(d).name() << std::endl;
    //std::cout << "d1 ptr: " << d1 << " type: " << typeid(*d1).name() << std::endl;
    //std::cout << "d2 ptr: " << d2 << " type: " << typeid(*d2).name() << std::endl;
    //std::cout << "d3 ptr: " << d3 << " type: " << typeid(*d3).name() << std::endl;
 
    getchar();
    return 0;
}
0
184 / 192 / 48
Регистрация: 25.08.2011
Сообщений: 792
21.02.2018, 11:58 8
Ygg, не работает потому что у вас две части от класса А. Ищите множественное, виртуальное наследование и читатйте теорию
0
Любитель чаепитий
3742 / 1798 / 566
Регистрация: 24.08.2014
Сообщений: 6,016
Записей в блоге: 1
21.02.2018, 12:10 9
Цитата Сообщение от Ygg Посмотреть сообщение
По-моему, вы как-то упустили про полиморфизм, а котором говорится у ТС.
ваш пример - не работает.
он работает только в студии, но это проблемы студии.
http://rextester.com/DQMCAL84184
на счёт полиморфизма и множественного наследования я действительно упустил.
тогда так:
C++
1
2
3
4
5
6
7
#include <typeinfo>
 
template<typename T>
bool isEqualObjects(const T * const lhs, const T * const rhs)
{
    return typeid(*lhs) == typeid(*rhs) && lhs;
}
Цитата Сообщение от Ygg Посмотреть сообщение
TC ссылается на какой-то видео ролик про 11 и 14 стандарты, может там что-то подходящее есть.
нет, это нас туда редиректит с недоступного "простым смертным" контента.
0
2376 / 834 / 317
Регистрация: 10.02.2018
Сообщений: 1,968
21.02.2018, 12:11 10
1Вирт1, грешен, в теории слабоват)
Есть случаи, когда использование virtual в определении наследования классов требуется, а есть когда не требуется.
Для полиморфного класса нужна хотя бы одна виртуальная функция. Правильнее было бы классы определить так.
C++
1
2
3
4
5
6
7
8
class A
{
public:
    virtual ~A() {}
};
class B : public A {};
class C : public A {};
class D : public A, B, C {};
Но динамик каст работает не совсем так, как хотелось бы. Хотя typeid заработал.
0
Любитель чаепитий
3742 / 1798 / 566
Регистрация: 24.08.2014
Сообщений: 6,016
Записей в блоге: 1
21.02.2018, 12:14 11
Цитата Сообщение от 1Вирт1 Посмотреть сообщение
не работает потому что у вас две части от класса А. Ищите множественное, виртуальное наследование и читатйте теорию
есть более простой пример, ломающий мою предыдущую функцию:
C++
1
2
3
4
5
6
7
struct A { virtual ~A() {} };
struct B : public A { virtual ~B() {} };
struct C : public B { virtual ~C() {} };
//...
C d;
A * a = &d;
A * b = (B*)&d;
0
2376 / 834 / 317
Регистрация: 10.02.2018
Сообщений: 1,968
21.02.2018, 12:23 12
GbaLog-, новая функция тоже не работает, она сравнивает типы, а не объекты.
C++
1
2
3
4
5
6
7
8
9
10
11
    D d;
    A* d1 = &d;
    A* d2 = (C*)&d;
    A* d3 = (B*)&d;
    D e;
    A* e1 = &e;
    A* e2 = (C*)&e;
    A* e3 = (B*)&e;
 
    std::cout << "isEqualObjects(d1, d2) return " << isEqualObjects(d1, d2) << std::endl;
    std::cout << "isEqualObjects(d1, e2) return " << isEqualObjects(d1, e2) << std::endl;
0
GbaLog-
21.02.2018, 12:32
  #13

Не по теме:

ладно, я чёт туплю.
пойду-ка отсюда.

0
Комп_Оратор)
Эксперт по математике/физике
8949 / 4703 / 629
Регистрация: 04.12.2011
Сообщений: 13,999
Записей в блоге: 16
22.02.2018, 08:53 14
Цитата Сообщение от Ygg Посмотреть сообщение
По-моему, вы как-то упустили про полиморфизм, а котором говорится у ТС.
Напишите шаблонную функцию, которая по двум однотипным указателям проверяет, указывают ли они на один объект - C++
Тут не может иметься ввиду полиморфизм. Хотя полиморфизм наследования (динамический) поддерживает неявное приведение (там каст не нужен, кстати), но это никогда не значило, что типы разных ступеней это один тип. Семантика "подтипизации" подразумевает нечто более похожее на включение, а семантика IS, - в свою очередь, - нечто похожее на возможность подстановки. Но это не подразумевает "однотипности". Как правило у таких типов даже размер разный, а не только поведение (набор методов) и набор состояний (данных). Поэтому, (imho) я считаю, что полиморфизм тут не при чем. Если преподаватель считает что полиморфизм тут "при чем", то полимозгизм порождает полимофную речь и фассеточное зрение. Это лечится. На ранних стадиях.

Добавлено через 1 минуту

Не по теме:

Цитата Сообщение от GbaLog- Посмотреть сообщение
пойду-ка отсюда.
Они Вас запутали GbaLog-. :)

0
2376 / 834 / 317
Регистрация: 10.02.2018
Сообщений: 1,968
22.02.2018, 14:34 15
Выдержка из документации dynamic_cast:
4) If expression is a pointer or reference to a polymorphic type, and new_type is a pointer to void, the result is a pointer to the most derived object pointed or referenced by expression.
Код:
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
#include <iostream>
#include <typeinfo>
 
class A
{
public:
    virtual ~A() {}
};
class B : public A {};
class C : public A {};
class D : public A, B, C {};
 
 
//  A    A
//  |    |
//  B    C    A
//  |    |    |
//  +----+----+
//  |
//  D
 
template<typename T>
bool isEqualObjects(const T * const lhs, const T * const rhs)
{
    return dynamic_cast<const void*>(lhs) == dynamic_cast<const void*>(rhs);
}
 
int main()
{
    D d;
    A* d1 = &d;
    A* d2 = (C*)&d;
    A* d3 = (B*)&d;
 
    D e;
    A* e1 = &e;
    A* e2 = (C*)&e;
    A* e3 = (B*)&e;
 
    std::cout << "isEqualObjects(d1, d2) return " << isEqualObjects(d1, d2) << std::endl;
    std::cout << "isEqualObjects(d1, e2) return " << isEqualObjects(d1, e2) << std::endl;
 
    std::cout << "d1 ptr: " << d1 << " cast: " << dynamic_cast<void*>(d1) << std::endl;
    std::cout << "d2 ptr: " << d2 << " cast: " << dynamic_cast<void*>(d2) << std::endl;
    std::cout << "d3 ptr: " << d3 << " cast: " << dynamic_cast<void*>(d3) << std::endl;
 
    std::cout << "e1 ptr: " << e1 << " cast: " << dynamic_cast<void*>(e1) << std::endl;
    std::cout << "e2 ptr: " << e2 << " cast: " << dynamic_cast<void*>(e2) << std::endl;
    std::cout << "e3 ptr: " << e3 << " cast: " << dynamic_cast<void*>(e3) << std::endl;
 
    getchar();
    return 0;
}
Результат:
isEqualObjects(d1, d2) return 1
isEqualObjects(d1, e2) return 0
d1 ptr: 000000D9EA1AFA08 cast: 000000D9EA1AFA08
d2 ptr: 000000D9EA1AFA18 cast: 000000D9EA1AFA08
d3 ptr: 000000D9EA1AFA10 cast: 000000D9EA1AFA08
e1 ptr: 000000D9EA1AFA98 cast: 000000D9EA1AFA98
e2 ptr: 000000D9EA1AFAA8 cast: 000000D9EA1AFA98
e3 ptr: 000000D9EA1AFAA0 cast: 000000D9EA1AFA98
Добавлено через 4 часа 21 минуту

Не по теме:

dynamic_cast - C++
Пять лет назад! А мы тут голову ломаем :D

0
Комп_Оратор)
Эксперт по математике/физике
8949 / 4703 / 629
Регистрация: 04.12.2011
Сообщений: 13,999
Записей в блоге: 16
22.02.2018, 22:14 16
Цитата Сообщение от Ygg Посмотреть сообщение
Пять лет назад! А мы тут голову ломаем
Время не всегда решает вопрос.
***
Приведение для расширяющего преобразования в иерархии не требуется.
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
#include <iostream>
using namespace std;
 
class T;
class S;
template<class A=T*, class B=S*>class ptr_compare
{
public:
    bool operator()(A a, B b){
return b==a;
    }
 
};
 
class Base{};
class Derived : public  Base {};
 
int main(int argc, char* argv[])
{
Base a;
Derived b;
Base *pa = &a;
Derived *pb =&b;
ptr_compare<Base*, Derived*>cmp;
 
cout<<cmp(pa, pb)<<endl;
pa=pb;
cout<<cmp(pa, pb)<<endl;
 
system("pause");
return 0;
}
Но и иерархия тоже не нужна. В задании сказано:
однотипные указатели (указатели на классы в иерархии это разнотипные)
а не
указатели на однотипные объекты (тут могли бы быть указатели на разные классы в иерархии указывающие на объект дочернего класса).
Или это я ничего не понял?
0
22.02.2018, 22:14
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
22.02.2018, 22:14
Помогаю со студенческими работами здесь

Дубликат класса. Widget1 и widget2 указывают на один и тот же объект
У меня есть абстрактный класс А, который является наследником QWidget, в своею очередь у меня есть...

Как проверить, указывают ли 2 открытых хендла на один и тот же физический объект? (напр., ключ реестра)
Собственно, сабж.

Написать функцию, которая проверяет что в строке содержится один пробел после знака препинания, и если нет - вставляет.
Написать функцию, которая проверяет что в строке, переданной в качестве аргумента, содержится один...

Напишите функцию, которая будет принимать один параметр
Напишите функцию, которая будет принимать один параметр. Функция должна вызывать себя столько раз,...


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

Или воспользуйтесь поиском по форуму:
16
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru