2014-09-18 3 views
0

У нас есть базовый класс .....станд :: shared_ptr Class Factory C++

class Node 
{ 
    public: 
     std::string Name; 
     Node(){}; 
     ~Node(){}; 
} 

фильтр является производным классом узла. Фильтр - это тот же узел, за исключением того, что он имеет свойство «filterId», и его конструктор заполняет Узел .Name = 'Filter'.

class Filter: public Node 
{ 
    public: 
     int filterId; 
     Filter() : Node() 
     { 
     Name="Filter"; 
     } 
} 

У меня есть ClassFactory, который возвращает std::shared_ptr<Node> при передаче строки

Пожалуйста, найти код для этого завода по CodeProject следующей ссылке.

http://www.codeproject.com/Articles/567242/AplusC-b-bplusObjectplusFactory.

код кажется инстанцировать фильтр, но возвращает узел. т.е. нарезка объектов.

std::shared_ptr<Node> n = std::make_shared(Node); // As expected, doesn't not have filter ID and node.Name is blank. 
std::shared_ptr<Filter> f = std::make_shared(Filter); // As expected, has filterID and node.Name is 'Filter'. 

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

std::shared_ptr<Node> nf = std::make_shared(Filter);  // Error. Does not have filterId, but does have **Node**.Name='Filter'. 

Я даже попробовал более простой случай ..... и получил ту же проблему.

Node n = Node(); 
Filter f = Filter(); 
Node nf =Filter(); // Error, nf does not have a filterID, but it's Name field is set to 'Filter'. 

Что я здесь делаю неправильно? Узел является базовым классом для всех моих производных классов. Когда у меня есть функция, которая принимает Узел, я должен быть в состоянии отправить его Фильтр и иметь доступ к фильтру.

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

+0

boost имеют shared_dynamic_cast – thomas

ответ

0

Если у вас есть какой-либо указатель или ссылка на базовый класс, вы можете получить доступ только к тем, которые предоставляет API базового класса. Если вы хотите получить доступ к filterId, вам необходимо либо:

  • добавить его к базовому интерфейсу (возможно, с функцией, которая возвращает boost::optional<int> или пару true,filterId при наличии, в противном случае, например, false,0) или

  • см., Если вы можете std::dynamic_pointer_cast на тип Filter, если возвращаемый указатель true в булевом контексте, вы можете использовать его для доступа к filterId.

1

Node не имеет каких-либо знаний о дополнительных элементов данных и функций, которые производные классы могут определить. Поэтому вам нужно получить shared_ptr<Filter>, чтобы иметь возможность получить доступ к filterId. Используйте std::dynamic_pointer_cast для этого.

std::shared_ptr<Node> n = ... 
auto f = std::dynamic_pointer_cast<Filter>(n); 

if(f) { 
    // The managed object is a Filter 
    std::cout << f->filter_id << '\n'; 
} 

Live demo

И если вы знаете, что n всегда содержит Filter (или что-то происходит от Filter), вы можете использовать вместо std::static_pointer_cast.

+0

Итак, если у меня есть вектор смешанных узлов и фильтров, как я могу отслеживать, что их бросать? – WebSight

+0

@ user2723463 Я изначально написал использование 'static_pointer_cast', но затем обновил свой ответ, чтобы вместо этого использовать' dynamic_pointer_cast'. Последнее касается вашего вопроса. Если вы попробуете 'dynamic_pointer_cast'' Node' для 'Filter', результирующий' shared_ptr' будет пустым. – Praetorian

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