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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> механизм виртуальных функций (не работает:(), иллюстрация классическим СИ 
V
    Опции темы
Podarochek
Дата 23.5.2008, 02:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



подскажите ошибку? smile 

Код

// Иллюстрация механизма виртуальных функций «классическим» Си
// Выделены компоненты, создаваемые транслятором
class A {
    void (**ftable)(); // Указатель на массив указателей
public: // виртуальных функций (таблицу функций)
    virtual void x(){}
    virtual void y(){}
    virtual void z(){}
    A();
    ~A(){} 
};
#define vx 0 // Индексы в массиве
#define vy 1 // указателей на виртуальные функции
#define vz 2 //
// Массив указателей функций класса А
void (*TableA[])() = { A::x, A::y, A::z };
A::A()

    ftable = TableA; /*...*/ // Назначение таблицы для класса А
}
class В : public A {
public:
    void x(){}
    void z(){}
    В();
    ~В(){}
};
// Массив адресов функций класса А в В
// А::у - наследуется из А, В::х - переопределяется в В
void (*TableB[])() = { В::x, A::y,В::z };
В::В()

    A::ftable = TableB; /*...*/ // Назначение таблицы для класса В
}
void main()
{
    
    В nnn; // Ссылается на объект производного класса В
    A *р = &nnn; // Указатель р базового класса А
    р->z();  // Реализация - (*(p->ftable[vz]))();
}



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


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


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

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



Цитата(Podarochek @  23.5.2008,  02:37 Найти цитируемый пост)
подскажите ошибку? 

Код

   void (**ftable)(); // указатели на статическую функцию
  
   virtual void x(){}
    virtual void y(){}
    virtual void z(){} // так они уже виртуальные )) 


A::ftable = TableB; // a ftable разве не в private: ? 



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


Шустрый
*


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

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



что значит эта ошибка:

Error    1    error C2440: 'initializing' : cannot convert from 'void (__thiscall A::* )(void)' to 'void (__cdecl *)(void)'

Добавлено через 3 минуты и 30 секунд
тут же все пом ок:

Код

void (*TableA[])() = { A::x, A::y, A::z };


Это сообщение отредактировал(а) Podarochek - 23.5.2008, 03:25
PM MAIL   Вверх
mes
Дата 23.5.2008, 03:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



Цитата(Podarochek @  23.5.2008,  03:24 Найти цитируемый пост)
error C2440: 'initializing' : cannot convert from 'void (__thiscall A::* )(void)' to 'void (__cdecl *)(void)'

компилятор не может преобразовать указатель_на_метод в указатель_на_статическую_функцию 
   void (**ftable)();   ->    void (**A::ftable)()


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


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


Шустрый
*


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

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



хм.. какой же нужно создать указатель?
Цитата(mes @  23.5.2008,  03:32 Найти цитируемый пост)
void (**ftable)();   ->    void (**A::ftable)()


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


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


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

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



Цитата(Podarochek @  23.5.2008,  03:39 Найти цитируемый пост)
хм.. какой же нужно создать указатель?

Цитата(mes @  23.5.2008,  03:32 )
void (**ftable)();   ->    void (**A::ftable)()


сорри что ввел в заблуждение синтаксисом

подразумевалось что вместо 
void (**ftable)(); должна быть примерно  void (A::**ftable)()

а вобше имхо что  подобный способ реализации виртуальных функций выбран не совсем правильно


P.S еше и звездочки перепутал..помойму засиделся я слишком 

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


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


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


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

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



вот набросал еше один вариант реализации  механизма виртуальных функций.

Код

#include <cstdlib>
#include <iostream>

using namespace std;

class A
{
 public:
    A() { A_vtable_init (); }
 public:
   void f1()              { A_vtable.f1(this); }
   void f2(int i)         { A_vtable.f2(this, i); }
   void f3(int i)         { A_vtable.f3(this, i); }

 private:
    void privf1() { cout << "  A::private_function()" ; }

 private:
   static void vf1(void* __this)  {
                                     cout << "A::f1() {";
                                     reinterpret_cast<A*>(__this)->privf1();
                                     cout <<"; };"<< endl; };

   static void vf2(void* __this, int i)  { cout << "A::f2(int)" << endl; };
   static void vf3(void* __this, int i)  { cout << "A::f3(int)" << endl; };

// VTABLE
   protected:
    class
    {
        public:
            void (*f1)(void* __this);
            void (*f2)(void* __this, int i);
            void (*f3)(void* __this, int i);
    } A_vtable;


    void A_vtable_init () {
                            A_vtable.f1=&A::vf1;
                            A_vtable.f2=&A::vf2;
                            A_vtable.f3=&A::vf3;
                          };

};

class B : public A
{
 public:
    B() { A_vtable_init (); }

 private:
    void privf1() { cout << "  B::private_function()" ; }
 private:
   static void vf1(void* __this)  {
                                     cout << "B::f1() {";
                                     reinterpret_cast<B*>(__this)->privf1();;
                                     cout <<"; };"<< endl; };
   static void vf2(void* __this, int i)  { cout << "B::f2(int)" << endl; };

   void A_vtable_init () {
                              A_vtable.f1=&B::vf1;
                              A_vtable.f2=&B::vf2;
                              A_vtable.f2=&B::vf2;
                          };

};


int main(int argc, char *argv[])
{
    A a;
    a.f1();
    a.f2(2);
    a.f3(6);

    cout <<endl;

    B b;
    b.f1();
    b.f2(3);
    b.f3(4);
    cout <<endl;

    A *pa=&b;
    pa->f1();
    pa->f2(4);
    pa->f3(5);

    cout <<endl;

    system("PAUSE");
    return EXIT_SUCCESS;
}



P.S 
Podarochek,  ты этой темой занялся из собственного любопытства или это задание?


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


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


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

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



Цитата(mes @  23.5.2008,  05:23 Найти цитируемый пост)
вот набросал еше один вариант реализации  механизма виртуальных функций.

В этом примере каждый объект  хранит таблицу виртуальных методов.
В связи с этим возможна ситуация что у двух объектов одного класса будут вызываться разные  методы - что не соответствует реальным виртуальным функциям. Будет свободное время - переделаю. 



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


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


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

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



вот со статической vtable для каждого класса..

Код

#include <cstdlib>
#include <iostream>

using namespace std;


class A
{
   protected:
// vtable-type -------------------------------
    class A_vtable_t
    {
        public:
            A_vtable_t() {};

        public:
            void (*f1)(void* __this);
            void (*f2)(void* __this, int i);
            void (*f3)(void* __this, int i);
    };
// --------------------------------------------

  public:
    A() { A_vtable_set(A_vtable_get_for_A()); }

  public:
// pseudo-virtual-interface
    void f1()              { A_vtable_get()->f1(this); }
    void f2(int i)         { A_vtable_get()->f2(this, i); }
    void f3(int i)         { A_vtable_get()->f3(this, i); }

  private:
    void priv_fn() { cout << "  A::private_function()" ; }

  private:
// pseudo-virtual-implementation

        static void vf1(void* __this)  {
                                          cout << "A::f1() {";
                                          reinterpret_cast<A*>(__this)->priv_fn();
                                          cout <<"; };"<< endl;
                                        };

        static void vf2(void* __this, int i)  { cout << "A::f2(int);" << endl; };
        static void vf3(void* __this, int i)  { cout << "A::f3(int);" << endl; };



  public:
//vtable-initialization
        static void A_vtable_init () {
                                       A_vtable_get_for_A()->f1=&A::vf1;
                                       A_vtable_get_for_A()->f2=&A::vf2;
                                       A_vtable_get_for_A()->f3=&A::vf3;
                                     };

   protected:
//vtable-details
        static A_vtable_t *A_vtable_get_for_A()       { static A_vtable_t  A_vtable_for_A; return &A_vtable_for_A; }

        A_vtable_t *A_vtable_get()                    { return A_vtable_ptr; }
        A_vtable_t *A_vtable_set(A_vtable_t * vtable) { A_vtable_ptr = vtable; }

   private:
        A_vtable_t * A_vtable_ptr;

};

class B : public A
{
 public:
        B() { A_vtable_set(A_vtable_get_for_B()); }

 private:
        void priv_fn() { cout << "  B::private_function()" ; }

 private:
// pseudo-virtual-implementation
        static void vf1(void* __this)  {
                                          cout << "B::f1() {";
                                          reinterpret_cast<B*>(__this)->priv_fn();;
                                          cout <<"; };"<< endl;
                                       };
        static void vf2(void* __this, int i)   { cout << "B::f2(int);" << endl; };

        static A_vtable_t *A_vtable_get_for_B() { static A_vtable_t  A_vtable_for_B; return &A_vtable_for_B; }

  public:
//vtable-initialization
        static void A_vtable_init () {
                                       *A_vtable_get_for_B()=*A_vtable_get_for_A();
                                        A_vtable_get_for_B()->f1=&B::vf1;
                                        A_vtable_get_for_B()->f2=&B::vf2;
                                     };

};


int main(int argc, char *argv[])
{
    A::A_vtable_init ();
    B::A_vtable_init ();

    A a;
    a.f1();
    a.f2(2);
    a.f3(6);

    cout <<endl;

    B b;
    b.f1();
    b.f2(3);
    b.f3(4);
    cout <<endl;

    A *pa=&b;
    pa->f1();
    pa->f2(4);
    pa->f3(5);

    cout <<endl;

    system("PAUSE");
    return EXIT_SUCCESS;
}




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


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Цитата(Podarochek @ 23.5.2008,  02:37)
подскажите ошибку? smile 

Код

// Иллюстрация механизма виртуальных функций «классическим» Си
// Выделены компоненты, создаваемые транслятором
class A {
    void (**ftable)(); // Указатель на массив указателей
public: // виртуальных функций (таблицу функций)
    virtual void x(){}
    virtual void y(){}
    virtual void z(){}
    A();
    ~A(){} 
};
#define vx 0 // Индексы в массиве
#define vy 1 // указателей на виртуальные функции
#define vz 2 //
// Массив указателей функций класса А
void (*TableA[])() = { A::x, A::y, A::z };
A::A()

    ftable = TableA; /*...*/ // Назначение таблицы для класса А
}
class В : public A {
public:
    void x(){}
    void z(){}
    В();
    ~В(){}
};
// Массив адресов функций класса А в В
// А::у - наследуется из А, В::х - переопределяется в В
void (*TableB[])() = { В::x, A::y,В::z };
В::В()

    A::ftable = TableB; /*...*/ // Назначение таблицы для класса В
}
void main()
{
    
    В nnn; // Ссылается на объект производного класса В
    A *р = &nnn; // Указатель р базового класса А
    р->z();  // Реализация - (*(p->ftable[vz]))();
}



Ошибка в том, что это именно иллюстрация и не надо рассматривать это как программу на С++. Если надо сделать по этой иллюстрации реальную программу, то ее надо делать на С (ибо в С++ это все и так есть) из этого исходника, предварительно 'обработав его напильником' до состояния правильного С сорца.

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


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


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

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



Код

иллюстрация классическим СИ 

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



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


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


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

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



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



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


Шустрый
*


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

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



Цитата(xvr @  23.5.2008,  13:29 Найти цитируемый пост)
void (**ftable)(); // Указатель на массив указателей

оператор поставил в protected
всеравно отстался вопрос:
Цитата(mes @  23.5.2008,  03:32 Найти цитируемый пост)
error C2440: 'initializing' : cannot convert from 'void (__thiscall A::* )(void)' to 'void (__cdecl *)(void)'

его реально решить в этой "иллюстрации"????



Цитата(xvr @  23.5.2008,  13:29 Найти цитируемый пост)
Ошибка в том, что это именно иллюстрация и не надо рассматривать это как программу на С++. Если надо сделать по этой иллюстрации реальную программу, то ее надо делать на С (ибо в С++ это все и так есть) из этого исходника, предварительно 'обработав его напильником' до состояния правильного С сорца.


стоит задача продемонстрировать механизм, никакой практической задачи. Как С++ никто не рассматривает об этом говорит постановка задачи .

Добавлено через 5 минут и 43 секунды
кстати..ссори что не по теме..подскажите что за ошибка:

Error    3    error LNK2001: unresolved external symbol "public: virtual double __thiscall Employee::earning(void)const " (?earning@Employee@@UBENXZ)    123.obj

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


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


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

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



Цитата(Podarochek @  23.5.2008,  15:19 Найти цитируемый пост)
оператор поставил в protected
всеравно отстался вопрос:

Цитата(mes @  23.5.2008,  03:32 )
error C2440: 'initializing' : cannot convert from 'void (__thiscall A::* )(void)' to 'void (__cdecl *)(void)'


его реально решить в этой "иллюстрации"????


а при чем тут ограничение доступа (protected) ?
ты пытаешься привести метод к указателю на функцию
решений два :
1. заменить массив указателей на функции массивом указателей на нужный тип метода
или
2. запихивать в массив не методы, а статические функции (но они не смогут работать с членам класса)

Добавлено через 5 минут и 45 секунд
Цитата(Podarochek @  23.5.2008,  15:19 Найти цитируемый пост)
стоит задача продемонстрировать механизм, никакой практической задачи. Как С++ никто не рассматривает об этом говорит постановка задачи .

такой механизм можно продемонстрировать только в OOП (там где есть наследие) - так что классический Си отпадает 
Цитата(Podarochek @  23.5.2008,  15:19 Найти цитируемый пост)
кстати..ссори что не по теме..подскажите что за ошибка:

Error    3    error LNK2001: unresolved external symbol 

линкер не нашел тела функции

Добавлено через 14 минут и 43 секунды
Цитата(Podarochek @  23.5.2008,  15:19 Найти цитируемый пост)
его реально решить в этой "иллюстрации"????

а чем тебя не устраивают примеры приведенные мной? 
(хочу заметить что твой пример далеко не Сишний)

Это сообщение отредактировал(а) mes - 23.5.2008, 15:35


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


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


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

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



а если реализовывать на Си то надо реализовывать классы и наследственность 


--------------------
PM MAIL WWW   Вверх
Страницы: (3) Все [1] 2 3 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
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.1512 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


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

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