Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > ошибка при использовании интерфейса


Автор: Alexander06 26.6.2009, 14:25
Здравствуйте,

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

Работу с каждым девайсом я описываю в отдельном классе, например 
Код

class PXI_6602: private TThread, public Interface_SSD_Device{
private:
    ...
    void __fastcall Execute();
public:
    int  init();
    int  start();

    PXI_6602(....);
    __fastcall ~PXI_6602();
};


Интерфейс Interface_SSD_Device объявлен как

Код

class Interface_SSD_Device{
    public:
    virtual int  init ()=0;
    virtual int  start()=0;
};


для того, чтобы в классе, создающем и управляющем объектами устройств обращаться к ним следующим образом

Создаем объект PXI_6602:

Код

Interface_SSD_Device* task;

task = (Interface_SSD_Device*) new PXI_6602(...);


И затем обращаемся к методам init и start объекта PXI_6602 или любого другого устройства строкой

Код

task->init();
task->start();


При этом происходит EAccessViolation.

В противном случае мне надо анализировать, какое именно у меня устройство, и делать вызов соответствующего объекта, например
Код


void* task;
if(type== TASK_6602)      
      task =(void*) new PXI_6602(...);

// далее везде делать проверки и соответствующие приведения и вызовы

if(type== TASK_6602)
      ((PXI_6602*)task)->init();

Так делать не хочется.

Подскажите, где я ошибаюсь в использовании интерфейса?

Автор: Леопольд 26.6.2009, 14:41
А без __fastcall не пробовали?

Если критична скорость, то следует избегать полиморфизма в рантайме. Вместо этого можно попытаться исопользовать шаблоны.?

Автор: Alexander06 26.6.2009, 15:16
Леопольд, __fascall - наследие класса TThread (C Builder), этот метод у меня лишь переопределяется.

В общем-то глючит не на его вызове, а при вызове метода init().
Почему-то конструкция
Код

task->init();

компилиться, но вызывает ошибку при выполнении. Как будто я не могу обраться к методу объекта Interface_SSD_Device* task.
Это странно, так как подобное использование приведено в http://ru.wikipedia.org/wiki/%D0%98%D0%BD%D1%82%D0%B5%D1%80%D1%84%D0%B5%D0%B9%D1%81_(%D0%BE%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D0%BD%D0%BE-%D0%BE%D1%80%D0%B8%D0%B5%D0%BD%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5)#C.2B.2B

Скорость тут не критична, вызов производится однократно. 

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

Автор: ИванМ 26.6.2009, 16:35
Здесь вроде ошибки нет. Скорее всего ошибка в коде функции init

Автор: Alexander06 26.6.2009, 20:49
Странно..Билдер даже на заходит в нее. Как если бы я попытался сделать ((PXI_6602*)some_ptr)->init() на неподходящем указателе.

Попробую написать небольшой тестовый пример в понедельник.

Спасибо за внимание.

Автор: DrHex 29.6.2009, 00:08
Скорее всего дело в твоем приведение.....

Подсказки:

Множественное наследования.....

Приведение типов при множественом наследовании..

Указатель на виртуальную таблицу......


Автор: Alexander06 29.6.2009, 18:13
Нашел в чем было дело - некоторые классы не реализовывали интерфейс.

На крики компилятора я делал так

Код

Interface_SSD_Device* task;
task = (Interface_SSD_Device*) new PXI_6602(...);


в то время при верном объявлении PXI_6602 должно работать и так

Код

Interface_SSD_Device* task;
task = new PXI_6602(...);


Естественно, ничем хорошим это кончиться не моглоsmile
Тема закрыта.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)