2010-11-26 50 views

Répondre

1

je suppose que vous avez déjà essayé de créer une méthode comme

void doSomething(std::vector<A*>& things) 
{ 
} 

et essayé ne passent

std::vector<B*> bList = ...; 
doSomething(bList); 

droit?

Pourquoi le compilateur se plaint-il? Parce que ça n'aurait pas de sens. Considérez que doSomething() essaie de faire

things.push_back(new C()); 

Cela ne peut pas fonctionner comme des « choses » est en fait un std::vector<B*>. Cependant, si c'était std::vector<A*>, push_back fonctionnerait.

Alors, que pouvons-nous apprendre de cela? Ce que vous essayez n'a de sens que si vous lisez seulement à partir du vecteur, cependant, le vecteur n'est pas un conteneur en lecture seule. Une enveloppe simple montre une solution possible (l'enveloppe peut être ajustée à vos besoins, bien sûr). Cependant, je dois souligner que l'utilisation de méthodes virtuelles pourrait entraîner des pénalités de performance.

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

template <class Base> 
class AbstractVectorWrapper 
{ 
public: 
    virtual size_t size() const = 0; 
    virtual Base* getElementAt(int index) const = 0; 
}; 
template <class Base, class Derived> 
class VectorWrapper : public AbstractVectorWrapper<Base> 
{ 
private: 
    std::vector<Derived*> m_vector; 
public: 
    explicit VectorWrapper(std::vector<Derived*> const& vector) 
     : m_vector(vector) 
    { 
    } 
    virtual size_t size() const 
    { 
     return m_vector.size(); 
    } 
    virtual Base* getElementAt(int index) const 
    { 
     return m_vector[index]; 
    } 
}; 

void doSomething(AbstractVectorWrapper<A> const& wrapper) 
{ 
    for (size_t i=0;i<wrapper.size();i++) 
    { 
     A* a = wrapper.getElementAt(i); 
    } 
} 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    std::vector<A*> as; 
    std::vector<B*> bs; 
    doSomething(VectorWrapper<A,B>(bs)); 
    doSomething(VectorWrapper<A,A>(as)); 


    return 0; 
} 
+0

Je savais que ce n'est pas possible d'où la question :-) – Gaurav

+0

je l'ai dit pourquoi il ne peut pas fonctionner, et non pas qu'il ne peut pas, par conséquent, ma réponse :-). – Philipp

+0

a ajouté une solution possible – Philipp

1

Est-duck-typing assez bon pour vous? Considérez ce code

template <class T> 
void my_function (std::vector <T*> const &values) { 
    // Use features of A* here 
} 

Cela ne parviendra pas à compiler si vous utilisez des fonctions des pointeurs vers T ne prennent pas en charge. En utilisant les fonctionnalités de A je pense qu'il devrait être garanti que les pointeurs vers B et C fonctionneront également comme prévu. Cependant, il serait possible d'appeler cette fonction avec des vecteurs de D *, à condition que l'interface de D soit conforme à ce que my_function essaie de faire.