2013-05-22 3 views
2

Короче говоря, у меня есть несколько классов, которые я создал для представления данных с разных устройств (на самом деле камеры). Оба они имеют разные поведения под капотом, но взаимодействие построено так же, как и снаружи. Я пытаюсь написать функцию полезности, которая может работать с любым классом или, предположительно, с другими классами, которые я пишу, если взаимодействие будет одинаковым. Я довольно новичок в C++, так что несите меня, если моя терминология не совсем правильная.Как использовать аргумент void * в C++ для нескольких типов объектов?

Так что давайте скажем, что у меня есть эти определения для каждой камеры.

class CamDataA 
{ 
int getImageStart() {return ptrToStart;) 
    int getImageSize() {return imageSizeVariable;) 
}; 

class CamDataB 
{ 
int getImageStart() {return ptrToStart;) 
    int getImageSize() {return width*height*channels;) 
}; 

И я хочу, чтобы иметь еще один отдельный класс, который может работать попеременно с обоих классов

class imageUtils 
{ 
    //constructors/destructors 

    int reportSize(void* camData) 
    { 
     cout << camData->getImageSize(); 
    } 

}; 

Но ошибка, я получаю при компиляции является:

error: ‘void*’ is not a pointer-to-object type 

Является ли это вообще возможно?

ответ

5

void * является нетипизированной указатель. Чтобы вызвать метод объекта с помощью указателя, указатель должен быть соответствующего типа. Вы можете явно указать свой void * на CamDataA* или CamDataB*, если знаете, на каком объекте он указывает, но это не то, что вы хотите (заранее не знаете тип объекта).

В вашем случае приятно использовать виртуальные методы.

1) Определить интерфейс . То есть определить набор методов без реализации.

class CamDataBase { 
    public: 
    virtual int getImageStart() = 0; // "=0" means abstract methods - MUST be 
    virtual int getImageSize() = 0; // overriden in descendants 
}; 

Ключевое слово virtual означает, что метод может быть переопределен в классах-потомках. Это означает, что если у нас есть указатель, скажем CamDataBase* p, и указатель указывает на некоторый класс потомков, например. p = new CamDataA(), и если мы напишем p->getImageStart(), тогда будет вызов метода, который соответствует действительному (текущему) типу объекта (CamDataA::getImageStart()), а не CamDataBase::getImageStart(), хотя p является указателем на CamDataBase.

2) Теперь определите пару реализаций интерфейса. Методы, которые имеют одну и ту же подпись как виртуальные методы в родительском классе переопределяют их.

class CamDataA: public CamDataBase { 
    int getImageStart() {return ptrToStart;) 
    int getImageSize() {return imageSizeVariable;) 
}; 
class CamDataB: public CamDataBase { 
    int getImageStart() {return ptrToStart;) 
    int getImageSize() {return width*height*channels;) 
}; 

3) Теперь определим функцию, которая принимает указатель на CamDataBase или любой из его потомков:

void reportSize(CamDataBase* camData) // using the base class 
{ 
    // type of the object and the appropriate method 
    // are determined at run-time because getImageSize() is virtual 
    std::cout << camData->getImageSize(); 
} 

А вот несколько примеров:

CamDataA A; 
CamDataB B; 
reportSize(&A); // CamDataA::getImageSize() is called 
reportSize(&B); // CamDataB::getImageSize() is called 

CamDataBase *p = &A; 
reportSize(p); // CamDataA::getImageSize() is called 

// and even if we cast pointer to CamDataA* to a pointer to CamDataB*: 
reportSize((CamDataB*)&A); // CamDataA::getImageSize() is called 

Я надеюсь, что вы будете искать в Интернете все слова, которые вам носят. :)

+0

ответ правильный, но я предлагаю вам отредактировать его, а также объяснить ему, что вы сделали и почему .. Я не думаю, что он понимает ОО, и это самая большая проблема, с которой он здесь столкнулся :) –

+0

Согласен, я может следовать коду, но все же не знаю конкретно, что вы сделали и почему. Благодаря! –

+0

Спасибо, я отредактирую ответ. Я просто надеялся, что слова «virtual» и «override» помогут ему начать изучение OOP :) Не уверен, что здесь есть подходящее место, чтобы вдаваться в подробности такой хорошо описанной темы, как полиморфизм. – Inspired

1

Кажется, что вторая функция - это нижний регистр, в то время как вы игнорировали ее как верхний регистр, и вы не передавали ее конкретному объекту. ((CamDataA *) camData) -> getImageSize ...

Однако это не способ сделать это на C++, я бы посоветовал вам прочитать немного больше об объектно-ориентированном ..., как делать приведение и использовать void * очень C как синтаксис.

С объектно-ориентированным вы можете иметь проверку типа (поскольку вы можете передать что-либо на void *), и они обеспечивают больше структуры и ясности для вашей программы. C++ (и другие объектно-ориентированные языки) используют базовый класс как контракт, который говорит, что все объекты этого типа должны иметь эти функции (метод), поэтому, например, базовый класс мешка определяет метод PutItemInBag, а затем рюкзак, чемодан, сумочку и т. д. все наследуют от сумки, и каждая из них может иметь другую реализацию PutItemInBag и обрабатывать ее по-разному, так как этот внешний объект может обрабатывать все мешки одинаково, не беспокоясь о том, какой объект он имеет, или если существует новый тип объекта в системе. Это делается с помощью виртуальных методов - Virtual Method Overview

Затем вы можете сделать базовый класс абстрактным, имея абстрактный виртуальный метод (что = 0 в C++). Это означает, что этот метод не имеет реализации, и вы не можете создавать объекты этого типа. Этот класс является только интерфейсом (или контрактом), а методы, которые наследуют его, должны переопределять этот метод и давать им собственную реализацию. Abstract Classes

Что вам нужно иметь оба класса имеет абстрактный базовый класс и обрабатывать его таким образом ..

class BaseCamData 
{ 
    virtual int getImageSize() = 0; 
}; 

//then have both class inherit form it. 
class CamDataA : public BaseCamData 
{ 
    virtual int getImageSize() {return 50;/*imagesize*/} 
} 

class CamDataB : public BaseCamData 
{ 
    virtual int getImageSize() {return 70;/*imagesize*/} 
} 




int reportSize(BaseCamData* camData) 
{ 
    count << camData->getImageSize(); 
} 

}

 Смежные вопросы

  • Нет связанных вопросов^_^