reference to a std::vector of derived class pointers as input parameter to a function
First of all I'd like to apologize if there's another question like this one and I didn't find it. I've been trying but since the problem is quite specific I couldn't find one.
Now, the problem. I have a Base class and a Derived class (say BNode and DNode ), and I have a std::vector of BNode*. I have also a function which receives a reference to a vector of these pointers. I'm having tro开发者_如何学Cuble when trying to pass a std::vector of pointers to derived objects as a parameter to this function:
class BNode
{
};
class DNode : public BNode
{
};
class Other
{
function(std::vector<BNode*>& inputVector) { }
}
When trying to pass a vector of pointers to the derived class, the error I'm receiving from VS is:
1> error C2664: 'Other::function' : cannot convert parameter 1 'std::vector<T>' to 'std::vector<T> &'
1> with
1> [
1> T=DNode *
1> ]
1> and
1> [
1> T=BNode *
1> ]
Thanks beforehand.
Your problem is that even if DNode
derives from BNode
, std::vector<DNode*>
doesn't derive from std::vector<BNode*>
.
Therefore, the compiler does not know how to convert from one type to the other.
You might however do:
std::vector<BNode*> bnode_list;
std::vector<DNode*> dnode_list(bnode_list.begin(), bnode_list.end());
This is because vector< Bnode* > and vector< Dnode* > do not have any parent-child relation. They are different objects.
I guess you have created a vector like std::vector< DNode* > dnodevec; Instead you can create std::vector< BNode* > dnodevec; Being the vector of base class pointers you can safely insert any DNode type pointer in the vector.
I suspect you are probably calling Other::function
something like this:
std::vector<DNode *> v;
// put stuff into v
Other o;
o.function(v);
Which won't compile, as std::vector<DNode *>
is a distinct type to std::vector<BNode *>
.
What may be suitable is:
std::vector<BNode *> v;
// You can put DNode * items into v
Other o;
o.function(v);
Unfortunately, what you want is not possible in C++, because vector<BNode*>
and vector<DNode*>
are considered to be unrelated types (even though there is a clear relation between BNode
and DNode
).
Consider the following code:
class BNode
{
};
class DNode : public BNode
{
};
class XNode : public BNode
{
};
void function(std::vector<BNode*>& inputVector)
{
inputVector.push_back(new XNode); // This will work, as XNode derived from BNode
}
int main()
{
std::vector<DNode*> vec;
function(vec); // Suppose this would work
// Then now, vec would contain a pointer to the unrelated class XNode!!
}
C++ doesn't support covariance in templates. An std::vector<DNode*>
cannot be assigned to an std::vector<BNode*>
even if DNode
derives from BNode
.
For your code to work, you should only declare vectors of pointers to BNode and populate them with pointers to DNode as needed.
std::vector
is not covariant.
In general, you should not pass a vector of DNode *
as a vector of BNode *
. If function
adds or replaces pointers to a subclass of BNode
different from DNode
, you would get non-DNode
pointers in your DNode *
vector.
You better change your types as explained in the other answers.
But contrary to what other answers say, it is possible to pass a vector of DNode *
if function
only reads the vector. To mark it so, change its signature to accept a const
reference. Then you can pass your DNode *
vector as follows:
function(reinterpret_cast<const std::vector<BNode *> &>(vec));
reinterpret_cast
is generally dangerous and you should avoid it unless you know very well what you are doing. Here, you are circumventing the C++ type system to treat a vector of DNode *
as a vector of BNode *
. Raw pointers are primitive types with the same binary representation regardless of the pointed-to type. Therefore the vectors of both pointer types are runtime compatible.
精彩评论