Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> ромбовидное наслежлвание, как пояснить компилятору чрез какую ветк 
V
    Опции темы
fuckingniger
  Дата 3.11.2010, 00:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 223
Регистрация: 1.10.2010

Репутация: нет
Всего: 1



ситуация такова:
           класс1
         /           \   
класс2            класс3
        \             /
          класс4

указатель на класс 1(по типу) нужно поставить на класс4
соответственно компилятор не знает  через какую ветку это ему делать ...как бы ему это сообщить???
PM MAIL   Вверх
Crafty
Дата 3.11.2010, 00:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 319
Регистрация: 3.11.2008

Репутация: 2
Всего: 14



Используйте виртуальное наследование.
Код

#include <iostream>

class A
{
public:
  virtual void print() { std::cout << "class A" << std::endl; }
  virtual~A() { }
};

class B: virtual public A
{
public:
  void print() { std::cout << "class B" << std::endl; }
};
class C: virtual public A
{
public:
  void print() { std::cout << "class C" << std::endl; }
};
class D: public B, public C
{
public:
  void print() { std::cout << "class D" << std::endl; }
};

int main()
{
  A *b = new D;
  b->print();
} 

PM MAIL   Вверх
fuckingniger
Дата 3.11.2010, 00:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 223
Регистрация: 1.10.2010

Репутация: нет
Всего: 1



так и сделано ...но дело в том что имеется массив указателей на класс 1 и нужно чтобы можно было указать на все классы ...т.к они производные.

то есть этот массив будет хранить указатели на все объекты этой иерархии
PM MAIL   Вверх
mes
Дата 3.11.2010, 00:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



1. static_cast, если известно что тип соответсвует,
2. dynamic_cast с проверкой соответсвия в рантайме
3. организовать архитектуру с сопоставлением иерархии объектов  к иерархии операций, 
подробнее в поиске по "двойная диспетчеризация"

Добавлено через 1 минуту и 27 секунд
тип наследования (ромбовидный) к проблеме не относится.. 



Это сообщение отредактировал(а) mes - 3.11.2010, 00:48


--------------------
PM MAIL WWW   Вверх
fuckingniger
Дата 3.11.2010, 01:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 223
Регистрация: 1.10.2010

Репутация: нет
Всего: 1



static помог спасибо
PM MAIL   Вверх
mes
Дата 3.11.2010, 01:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(fuckingniger @  3.11.2010,  00:08 Найти цитируемый пост)
static помог спасибо 

чтоб быть уверенными что он помог правильно, разберитесь внимательно когда нужно использовать статик_каст, а когда диамик_каст..


--------------------
PM MAIL WWW   Вверх
fuckingniger
Дата 3.11.2010, 01:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 223
Регистрация: 1.10.2010

Репутация: нет
Всего: 1



Код

vector <worker*>workers(number_workers); 

Код

    worker_procent_of_sum* ptr = dynamic_cast <worker_procent_of_sum*> (workers[0]);


Код

 'worker' is not a polymorphic type
 see declaration of 'worker'


declaration of 'worker'
Код

#ifndef WORKER_H
#define WORKER_H
# include <string>
using namespace std;
class company;
struct name
{
    string first_name;
    string last_name;
};
class worker
{
protected:
    string first_name;
    string last_name;
    int time_of_work;
public:
    worker(string s1, string s2 , int time,company& company_1);
    string get_first_name();
    string get_last_name();
    void print();
};
#endif


Код

#ifndef WORKER_PROCENT_OF_SUM 
#define WORKER_PROCENT_OF_SUM 

# include "worker.h"
# include <iostream>
using namespace std;
class worker_procent_of_sum:public worker
{
public:
    worker_procent_of_sum(string s1,string s2,int d,company& company_1,double sum,double prc) ;
    void set_sum_all(double);
    void set_percent(double);
    double salary();
    void print ();
protected:
    double sum_all;
    double percent;
};
#endif



почему такая ошибка ?...ведь вроде бы всё правильно написано worker_procent_of_sum наследник  worker и почему тогда он не полтиорфный ???
PM MAIL   Вверх
mes
Дата 3.11.2010, 01:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



полиморфным класс становится при наличии хотя бы одной виртуальной функции ( в том числе и виртуального деструктора)..



--------------------
PM MAIL WWW   Вверх
fuckingniger
Дата 3.11.2010, 01:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 223
Регистрация: 1.10.2010

Репутация: нет
Всего: 1



а dynamic_cast только к полиморфным можно применять? чем простые хуже?
PM MAIL   Вверх
mes
Дата 3.11.2010, 01:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(fuckingniger @  3.11.2010,  00:51 Найти цитируемый пост)
а dynamic_cast только к полиморфным можно применять? чем простые хуже? 

тем что не хранят информацию о наследственных связях в рантайме.. 


--------------------
PM MAIL WWW   Вверх
fuckingniger
Дата 3.11.2010, 01:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 223
Регистрация: 1.10.2010

Репутация: нет
Всего: 1



то есть если я щас возьму сделаю 1 полиморфную функцию в worker то всё заработает?

Добавлено через 3 минуты и 1 секунду
и правда ошибки не стало ...чудеса да и только 
PM MAIL   Вверх
mes
Дата 3.11.2010, 02:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(fuckingniger @  3.11.2010,  00:59 Найти цитируемый пост)
то всё заработает? 

насчет всего не знаю, но эта ошибка пропадет ..
 smile 

Это сообщение отредактировал(а) mes - 3.11.2010, 02:03


--------------------
PM MAIL WWW   Вверх
fuckingniger
Дата 3.11.2010, 02:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 223
Регистрация: 1.10.2010

Репутация: нет
Всего: 1



извините, что столько вопросов, но не клеится что-то сегодня .

имеется массив указателей на класс1 под названием workers

я при помощи static_cast преобразую указатель на класс4(из 1 поста) к классу1(чтоб хранить можно было в массиве) а потом для вызова специфических функций класса 4 делаю обратное преобразование при помощи dynamic_cast . вылетает след ошибка : 

user posted image
PM MAIL   Вверх
Леопольд
Дата 3.11.2010, 08:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 943
Регистрация: 17.6.2009

Репутация: 10
Всего: 13



Цитата(fuckingniger @  3.11.2010,  02:15 Найти цитируемый пост)
я при помощи static_cast преобразую указатель на класс4(из 1 поста) к классу1(чтоб хранить можно было в массиве)
От производного к базовому кастуется без вмешательсва программиста (т.е. без static_cast'а).
Код
struct Parent { virtual ~Parent() {} };
struct Child1: public Parent { char data; };
struct Child2: public Parent { int data; };

Child1 child;
Parent * pPtr = &child;
 (При этом указатель на таблицу виртуальных функций остаётся прежним, что приводит к вызову виртуальных функций из производного, в данном случае, если сделать delete pPtr; то будет вызван деструктор Child1.)
Обратного неявного преобразования нет, поэтому нужно указывать static_cast. Однако, это "опасное" действие, потому что можно сделать так:
Код
Child2 * cPtr = static_cast<Child2 *>(pPtr);
это приводит к UB (undefined behaviour - неопределённое поведение) Запускаем, и смотрим что получилось:
Код
struct Parent {
    virtual void foo() = 0;
protected:
    ~Parent() {} //разрушать объект через указатель на Parent нельзя
};
struct Child1: public Parent { virtual void foo() {std::cout<<"Child1"<<std::endl;} };
struct Child2: public Parent { virtual void foo() {std::cout<<"Child2"<<std::endl;} };

int main()
{
    Child1 child;
    Parent * pPtr = &child;
    Child2 * cPtr = static_cast<Child2 *>(pPtr);
    cPtr->foo();

    //delete pPtr; //error: ‘Parent::~Parent()’ is protected

    return 0;
}


Добавлено @ 08:24
Цитата(fuckingniger @  3.11.2010,  02:15 Найти цитируемый пост)
вылетает след ошибка 
Возможно, выскакивает std::bad_cast (правда он возникает когда приводишь ссылки, а не указательи). 
http://cplusplus.com/reference/std/typeinfo/bad_cast/
Поведение dynamic_cast не очень очевидно. В случае с указателями, исключения не возникает, но указатель устанавливается в NULL. В случае с ссылками, вылетает исключение bad_cast (просто потому что ссылку нельзя установить в NULL)
Код
struct Parent {
    virtual void foo() = 0;
    virtual ~Parent() {} //удалять через указатель на Parent можно
};
struct Child1: public Parent {
    virtual void foo() {std::cout<<"Child1"<<std::endl;}
    virtual ~Child1() {std::cout<<"~Child1"<<std::endl;}
};
struct Child2: public Child1 {
    virtual void foo() {std::cout<<"Child2"<<std::endl;}
    virtual ~Child2() {std::cout<<"~Child2"<<std::endl;}
};
// здесь Child2 наследуется от Child1

int main()
{
    Child1 * cPtr = new Child1;
    Parent & pRef = *cPtr;
    
    try{
        Child2 & cRef = dynamic_cast<Child2 &>(pRef);
        cRef.foo();
    }
    catch(std::exception &e)
    {
        std::cout<<e.what()<<std::endl;
    }

    delete &pRef;
    
    return 0;
}



Это сообщение отредактировал(а) Леопольд - 3.11.2010, 08:41


--------------------
вопросов больше чем ответов
PM MAIL   Вверх
baldina
Дата 3.11.2010, 11:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



Цитата(fuckingniger @  3.11.2010,  02:15 Найти цитируемый пост)
извините, что столько вопросов, но не клеится что-то сегодня .

Проверьте, включено ли в параметрах проекта runtime type info
нужно для работы dynamic_cast, по умолчанию в VC выключено
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0672 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.