2016-10-15 3 views
-1

Я пытаюсь сохранить различные подклассы в векторе unique_ptr <BaseClass>. Этот подход, похоже, работает, когда подклассы являются одним слоем, но не удается, когда подклассы имеют два слоя.Сохранение различных подклассов в векторе

Вот что я пытаюсь сделать

#include <iostream> 
#include <memory> 
#include <vector> 

using namespace std; 

class A 
{ 
    int foo; 
public: 

    explicit A(int bar) 
    { 
     foo = bar; 
    } 

    int getFoo() 
    { 
     return foo; 
    } 

    virtual void func1() = 0; 
}; 

class B : public A 
{ 
public: 
    using A::A; 
}; 

class C : public A 
{ 
public: 
    virtual void func2() = 0; 
    using A::A; 
}; 

class D : public B 
{ 
public: 

    using B::B; 

    void func1() 
    { 
     cout << "D1" << endl; 
    } 
}; 

class E : public C 
{ 
public: 

    using C::C; 

    void func1() 
    { 
     cout << "E1" << endl; 
    } 
    void func2() 
    { 
     cout << "E2" << endl; 
    } 

}; 

int main() 
{ 
    vector<unique_ptr<A> > vec; 
    vec.emplace_back(new D(1)); 
    vec.emplace_back(new E(2)); 
    vec[0]->func1(); // Okay 
    vec[1]->func1(); // Okay 
    vec[1]->func2(); // error: 'class A' has no member named 'func2' 
    E foo(3); 
    foo.func2(); // Okay 

    return 0; 
} 

ответ

0

Поскольку вы сохраняете указатели только на класс A, вы можете вызвать func1, если он перегружен.

Однако func2 не существует внутри класса A, поэтому даже если указатель является указателем на класс C, который имеет func2, вы обрабатываете его как указатель на класс A, поэтому вы не можете вызвать func2, потому что func2 doest ничего не значит в контексте класса А.

0

Вы должны смотреть на то, как работает полиморфизм: если у вас есть указатель на А вы можете назвать только один из его методы. В вашем примере A :: func2() не имеет смысла

0

В полиморфизма, вам нужно реализовать все методы, которые вы собираетесь использовать позже в классе вы на самом деле, указывая на:

class A 
{ 
public: 
    virtual void func(); 
    virtual void func2(); 
} 

class B : public A 
{ 
public: 
    void func(); 
} 
class C : public A 
{ 
public: 
    void func2() 
} 

То же самое относится и к переменным. Теперь, если вы собираетесь называть func2 of A, буквально ничего не произойдет. Если у вас есть обратные типы, вам нужно искать более умное решение.

0

Ваша проблема не имеет ничего общего с тем, как вы храните указатель. Проблема в том, что А не имеет метода func2.

A* p = new E(2); 
    p->func2(); 

также потерпят неудачу.

Либо вам нужно добавить func2 в A, либо передать p в указатель E.