2013-07-19 2 views
0

Мое дело в следующем: в моей более крупной программе я хочу создать интерфейс для захвата кадров из источника изображения. Однако в программе я не знаю заранее, хочу ли я захватить кадры из камеры или из видеофайла. Но я хотел бы иметь один интерфейс, который обрабатывает видеофайлы и рамки камеры как идентичные. Это, в общем, требует много кода для выполнения, поэтому я приведу очень короткий пример.Возможно ли создать экземпляр интерфейса без указателей?

это пример интерфейса:

class Input { 

    public : 

     virtual void 
     get_frame() = 0; 
}; 

Это производный класс, который должен захватывать кадры из камеры.

class CameraInput: public Input { 

    public : 
     void get_frame(); 
}; 

Это класс, который должен открыть видеофайл и захватить кадры из файла.

class VideoInput: public Input { 

    public : 

     void get_frame(); 

}; 

Вот определения get_frame из классов входных получено. Как вы можете видеть, они «производят» различные типы видеокадров.

void 
CameraInput::get_frame(){ 
    std::cout << "camera-frame" << std::endl; 
}; 

void 
VideoInput::get_frame() { 
    std::cout << "video-frame" << std::endl; 
}; 

этого кода, который создает экземпляр объекта типа CameraInput или VideoInput.

Редактировать общий указатель добавлен

typedef enum { VIDEO, CAMERA } input_type ; 
std::shared_ptr<Input> framegrabber; 
/*Does this have to be a pointer?*/ 

/*In my program I don't know this in advance.*/ 
input_type my_input = CAMERA; 

switch (my_input){ 
    case CAMERA: 
     framegrabber = std::shared_ptr<Input>(new CameraInput); 
     break; 
    case VIDEO: 
     framegrabber = std::shared_ptr<Input>(new VideoInput); 
     break; 
    default: 
     /*error handling here*/ 
     break; 
}; 

framegrabber->get_frame(); 

На StackOverflow я много раз читал в С ++ отвечает, что никогда не следует использовать указатели, если только один действительно, на самом деле не нужно. Вот откуда мой вопрос: возможно ли и лучше переписать код выше, не используя Input*, или это один из тех случаев, когда обязательно использовать указатели?

Уважением,

+2

Вы должны хотя бы использовать какой-нибудь умный указатель там – PlasmaHH

+0

Нет, это невозможно. Зачем вам это делать? –

+0

@PlasmaHH согласен, я сделаю это, но это не отвечает на мой вопрос. – hetepeperfan

ответ

3

На StackOverflow я много раз читал в с ++ отвечает, что никогда не следует использовать указатели, если только один действительно, на самом деле не нужно.

Когда вы читаете какие-либо советы, вы должны попытаться понять ПОЧЕМУ этот совет дан. Если нет никаких оснований для совета, нет необходимости следовать этому совету.

Попытка устранить все указатели из вашей программы только потому, что кто-то сказал вам, что «указатели плохие» - это не очень хорошая идея.

Опытные программисты говорят, что вы избегаете использования raw-указателей, поскольку указатели означают ручное управление памятью, которое подвержено ошибкам (забудьте удалить что-то == утечка памяти), плюс вы должны знать о rule of three.
У меня также сложилось впечатление, что неопытные программисты часто дают тот же совет, потому что они просто не понимают указателей полностью (или боятся их?).

Вы можете использовать ссылки, но поскольку вы не можете копировать/переназначать ссылки, которые будут менее полезными. Пример:

#include <iostream> 

class A{ 
public: 
    virtual int getVal() const = 0; 
    virtual ~A(){} 
}; 

class B: public A{ 
public: 
    virtual int getVal() const { return 2; }; 
}; 

class C: public A{ 
public: 
    virtual int getVal() const { return 3; }; 
}; 

class D{ 
public: 
    const A& getInterface(bool which) const{ 
     if (which) 
      return c; 
     return b; 
    } 
protected: 
    B b; 
    C c; 
}; 

int main(int argc, char** argv){ 
    D d; 
    std::cout << d.getInterface(true).getVal() << std::endl; 
    std::cout << d.getInterface(false).getVal() << std::endl; 
    return 0; 
} 

Как вы можете видеть, чтобы вернуть объект по ссылке, вам нужно создать его где-нибудь и сохранить его. Если вы хотите «убить все указатели», вам нужно будет создать этот объект как переменную-член большего класса (или как глобальную переменную).

С указателем вы можете просто вернуть shared_ptr<A>.

В вашем коде лучше будет использовать класс smart pointer вместо необработанных указателей. Это устранит необходимость ручного управления удалением/памятью.

возможно и лучше rewite код выше без использования входа *

Да, это возможно, но нет никаких причин, чтобы сделать это, и это (ИМО) не лучше. Мой пример иллюстрирует, как вы могли это сделать. Без указателей (любого вида - умного или необработанного) вам также нужно будет хранить BOTH CameraInput и VideoInput, а с указателями вы можете создавать их по требованию.

+0

Спасибо за подробный ответ. Ваш ответ также объяснил мне, почему (умный) подход указателя лучше здесь, так как я бы не хотел создавать интерфейс, который пытается загрузить как видео из файла, так и получить извлечения кадров из камеры. – hetepeperfan

+0

Необработанные указатели - просто предположите по умолчанию, что они не владеют чем-либо и являются просто ссылочными и нулевыми ссылками, потому что это единственное, что они должны использовать на данный момент (ну, с нечетным исключением для низкоуровневого здания блоки). – Xeo

0

Вы можете использовать смарт-указатель (например, станд :: unique_ptr или станд :: shared_ptr) вместо сырых указателей.
Если вам нужен полиморфизм, вы должны обязательно использовать указатели или ссылки. Есть гораздо больше деталей, чем вы действительно хотите here

+1

Я бы подумал о замене * unqiue_ptr * и * sahred_ptr * на что-то еще. –

+0

Не могли бы вы привести пример, как это можно сделать с переменной по ссылке? – hetepeperfan

+0

@MarkusMeskanen в последнем абзаце я объясняю, почему я задал этот вопрос. Я не говорю, что указатель ошибочен, несмотря ни на что. – hetepeperfan