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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> RTTI 
:(
    Опции темы
Graf_h
Дата 24.9.2009, 22:38 (ссылка)  | (голосов:3) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 482
Регистрация: 18.10.2007
Где: г. Ровно, Украина

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



Привет. Интересует вопрос, как компилятор понимает тип обьекта (по каким именно критериям)? Как происходит приведения типов. Почему любой указатель можно привести к *void.  Как в иерархии наследования компилятор знает родителей и т.д. Заранее спасибо 


--------------------
Иногда переменная - это просто переменная
PM MAIL ICQ   Вверх
jonie
Дата 24.9.2009, 22:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 5613
Регистрация: 21.8.2005
Где: Владимир

Репутация: 15
Всего: 118



Цитата

Почему любой указатель можно привести к *void. 
по стандарту языка. Указатель это всего лишь адрес в памяти. Типы указателей существуют только на этапе компиляции (для адресации по указателю используется знания о типе указателя).


на многие вопросы можно найти ответы тут: http://www.rsdn.ru/article/cpp/fastdelegate.xml


--------------------
Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет...
PM MAIL Jabber   Вверх
mes
Дата 25.9.2009, 11:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



Цитата(Graf_h @  24.9.2009,  21:38 Найти цитируемый пост)
Интересует вопрос, как компилятор понимает тип обьекта

Программист определяет тип объекту, а компилятор его ассоциацивно запоминает или выводит из имеющихся  данных.


Цитата(Graf_h @  24.9.2009,  21:38 Найти цитируемый пост)
Почему любой указатель можно привести к *void

Так договорились, для удобства  smile 


Цитата(Graf_h @  24.9.2009,  21:38 Найти цитируемый пост)
Как в иерархии наследования компилятор знает родителей

так же как и в первом случае, потому что программист указал это : class Derived: public Base {};

Посмотрел на название темы RTTI, значит интересует dynamic_cast ?
один из вариантов реализации, для сравнения типов объектов, сравнивать указатель на виртуальную таблицу.



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


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


Опытный
**


Профиль
Группа: Участник
Сообщений: 482
Регистрация: 18.10.2007
Где: г. Ровно, Украина

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



Цитата(mes @  25.9.2009,  11:42 Найти цитируемый пост)
Программист определяет тип объекту, а компилятор его ассоциацивно запоминает или выводит из имеющихся  данных.

Я понимаю что программист описывает тип. Давайте покажу на примере:

Код

class A{
       int a;
       int b;
       int c;

}

class B{
       int a;
       int b;
       int c;

}

A a;
B b;
a=b;


Выдаст ошибк.Интересует вопрос, как именно это знает компилятор?? 


Цитата(mes @  25.9.2009,  11:42 Найти цитируемый пост)
один из вариантов реализации, для сравнения типов объектов, сравнивать указатель на виртуальную таблицу.

А если нету виртуальных методов, соответственно виртуальная таблица не создастся, правильно??



--------------------
Иногда переменная - это просто переменная
PM MAIL ICQ   Вверх
Graf_h
Дата 25.9.2009, 14:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 482
Регистрация: 18.10.2007
Где: г. Ровно, Украина

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



В принципе вообще можно обойтись только функцией memcpy, ведь в исполняемом файле нету такого понятия, там просто набор байтов. 

Вот провел небольшой тест:

Код

#include "stdafx.h"
#include <iostream>

class A{
public:
    int a;
    int b;
    A(){
        a=1;
        b=2;
    }
    void res1(){
        std::cout<<a<<"  "<<b<<std::endl;
    }
};

class B{
    public:
    int a;
    int b;
    B(){
        a=11;
        b=21;
    }

    void res1(){
        std::cout<<a<<"  "<<b<<std::endl;
    }
};

int _tmain(int argc, _TCHAR* argv[]){
    A a;
    B b;
    
    a.res1();
    b.res1();

    memcpy(&b,&a,sizeof(A));

    b.res1();
    while(1){
    
    };
    return 0;
}


результаты:
1 2
11 21
1 2


Зачем нам тогда static_cast dynamic_cast и т.д.smile


Это сообщение отредактировал(а) Graf_h - 25.9.2009, 14:25


--------------------
Иногда переменная - это просто переменная
PM MAIL ICQ   Вверх
bsa
Дата 25.9.2009, 14:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

Репутация: 63
Всего: 196



Graf_h, копирование с помощью memcpy допустимо только для POD объектов. Сложные объекты (например, конструкторы которых выделяют память, а деструкторы ее освобождают) копировать так НЕЛЬЗЯ!
PM   Вверх
Static
Дата 25.9.2009, 16:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



2bsa
Я правильно понимаю сказанное? Например:
Код

class SomeClass
{
SomeClass(): id(0), x(0.0f), y(0.0f), z(0.0f) { };

int id;
float x, y, z;
float S;
}; //объект можно скопировать через memcpy

class NetPackage
{
NetPackage(int a, int b): id(a), len(b) {data = new char[len];}

int id;
int len;
char* data;
}; //нельзя


--------------------
Я не настолько безнадежен, как кажется...
PM MAIL   Вверх
Graf_h
Дата 25.9.2009, 16:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 482
Регистрация: 18.10.2007
Где: г. Ровно, Украина

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



Static,  bsa правду говорит. Скопировать то можно, но тогда неизбежны утечки памяти. Хотелось бы все же узнать как  компилятор знает тип обьекта(имеется ввиду dynamic_cast)??

Это сообщение отредактировал(а) Graf_h - 25.9.2009, 16:58


--------------------
Иногда переменная - это просто переменная
PM MAIL ICQ   Вверх
mes
Дата 25.9.2009, 22:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



Цитата(Graf_h @  25.9.2009,  11:03 Найти цитируемый пост)
А если нету виртуальных методов, соответственно виртуальная таблица не создастся, правильно??

да, по этой самой причине нельзя примянять к объектам таких классов динамик_каст.



Цитата(Graf_h @  25.9.2009,  13:06 Найти цитируемый пост)
Вот провел небольшой тест:
Зачем нам тогда static_cast dynamic_cast и т.д.smile


Затем чтоб избавить программиста от ручных преобразований и дать ему по рукам если компилятор в силах определить ошибочность.

Цитата(Graf_h @  25.9.2009,  15:58 Найти цитируемый пост)
. Хотелось бы все же узнать как  компилятор знает тип обьекта(имеется ввиду dynamic_cast)??

компилятору не нужно знать реальный тип объекта в реале, главное может ли произойти нужное преобразование,
т.е. (для динамик_каста) можно ли привести имеющийся указатель к тому который запросил программист.
В виртуальной таблице (ВMТ) наследника, хранится указатель на ВMТ предка, и этим  образуют "список наследования"
осталось только проверить находится ли указатель на ВMТ в нужном списке наследования и если нет, то вернуть ноль, это и делает dynamic_cast.

Это сообщение отредактировал(а) mes - 26.9.2009, 13:43


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


Опытный
**


Профиль
Группа: Участник
Сообщений: 482
Регистрация: 18.10.2007
Где: г. Ровно, Украина

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



mes большое спасибо +1. Еще хотелось бы уточнить насчет в-табл. 
Код

class A{
public:

   virtual void a();
}

class B:public A{
public:

   virtual void a();
}


Это по сути 2 разные функции, 2 разных адресса. Как компилятор знает что это переопределенная функция?? 
Код

A* a
B* b=new B();
a=b
a->a();


каким образом здесь вызывактся нужная функция(класса В). Ведь по сути класс А совсем ничего не знает о своем потомке. Хотя, с другой стороны, это адресс обьекта B. Почему тогда я не могу вызвать функции которые не описаны в родителе?

Это сообщение отредактировал(а) Graf_h - 25.9.2009, 22:50


--------------------
Иногда переменная - это просто переменная
PM MAIL ICQ   Вверх
mes
Дата 25.9.2009, 23:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



Цитата(Graf_h @  25.9.2009,  21:50 Найти цитируемый пост)

каким образом здесь вызывактся нужная функция(класса В). Ведь по сути класс А совсем ничего не знает о своем потомке. Хотя, с другой стороны, это адресс обьекта B.


вызов виртуальной функции pa->f() грубо говоря представлен как (pa-> pa->vmt->  f)(); где  pVMT указатель на виртуальную таблицу (устанавливается в конструкторе)
который для каждого класса другой.


Это сообщение отредактировал(а) mes - 25.9.2009, 23:43


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


Опытный
**


Профиль
Группа: Участник
Сообщений: 482
Регистрация: 18.10.2007
Где: г. Ровно, Украина

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



mes, я видимо что то не доганяю. Если у нас есть виртуальная функция func() в родителе, то в потомке такая же функция будет совсем по другому адресу(другая функция с тем же именем). Вопрос собсно в том как компилятор знает что это именно та функция которую нужно переопределить?


--------------------
Иногда переменная - это просто переменная
PM MAIL ICQ   Вверх
mes
Дата 26.9.2009, 00:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



Цитата(Graf_h @  25.9.2009,  21:50 Найти цитируемый пост)
Почему тогда я не могу вызвать функции которые не описаны в родителе?

можете, надо явно указать тогда чей метод хотите вызвать.

Судя по Вашим постам, основное заблуждение в том, что Выт думаете что компилятор при разборе видит только ту строчку которую он разбирает, и что вся нужная информация содержится в ней.
На самом деле очень много "грязной" информации программист не видит, и это упрощает написание кода, однако затрудняет понимание самого процесса происходящего, в случае если программист не знает как все это на самом деле работает. 
/*
В частности поэтому многие недолюбливают Си++:
 одни из них (обычно сишники  с опытом)  прекрастно представляют как это работает и могут легко получать это обычными си-средствами, а так как привыкли все и вся контролировать сами, помощь компилятора им просто излишна.
 другие  не понимают что творится, но видят что на других языках, в том числе и на Си таких замудреностей нет, поэтому  боятся  Си++ и избегают его.
*/

Так вот когда метод указан как виртуальный, вместо вызова встраивается дополнительный код, который вызывает нужную функцию (опираясь на VMT)

Добавлено @ 00:13
Цитата(Graf_h @  25.9.2009,  22:47 Найти цитируемый пост)
, то в потомке такая же функция будет совсем по другому адресу

Да но эта функция при виртуальном вызове не будет вызвана напрямую. Адрес каждой из них хранится в своей VMT,
а объект при конструировании всегда получает указатель на "свою" VMT, относительно которой и происходит вызов.

Добавлено @ 00:17
Вот здесь был приведен пример по иллюстрации работы виртуального механизма : http://forum.vingrad.ru/index.php?showtopi...t&p=1524278

Это сообщение отредактировал(а) mes - 26.9.2009, 13:44


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


Опытный
**


Профиль
Группа: Участник
Сообщений: 482
Регистрация: 18.10.2007
Где: г. Ровно, Украина

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



Цитата(mes @  26.9.2009,  00:05 Найти цитируемый пост)
Вот здесь был приведен пример по иллюстрации работы виртуального механизма : http://forum.vingrad.ru/index.php?showtopi...t&p=1524278 

Большое спасибо за ссылку, и за то, что вы есть на этом форуме smile. Буду разбиратся.


--------------------
Иногда переменная - это просто переменная
PM MAIL ICQ   Вверх
mes
Дата 28.9.2009, 20:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



Цитата("UnrealMan")

Дважды соврал про dynamic_cast

Ну хотя бы вкратце показали бы где smile



--------------------
PM MAIL WWW   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

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

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

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

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


 




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


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

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