Casting array of pointers to objects
If B
is subclass of A
.
And I have in main()
:
B** b = new B*[10];
... // some algorithm that does b[i] =开发者_如何学运维 new B(..);
So I have an array of pointers to objects B
.
Then I have a function:
void f(A** foo);
If in main, I do: f(b);
I get a warning, but obviously if I do: f((A**)b);
, I don't.
The (A**)
its a bit nasty. I was wondering if there's a more elegant way in C++ that at least do type checking as dynamic_cast
.
I want foo to sort (only using swaps) arrays of objects of type A or subclass.. so make a generic sorting algorithm. I hope now you understand better my problem.
A**
and B**
are two totally different types. Just because there is an implicit conversion from B*
to A*
does not mean that the same conversion exists from B**
to A**
See this FAQ Converting Derived* → Base* works OK; why doesn't Derived** → Base** work? for more details.
There's a reason you get a warning or error if you try to implicitly cast a B**
to a A**
: it's not safe to do so.
Referring to the array as a A**
allows you to put pointers to A
objects inside. For an array of B*
this is wrong and therefor the cast is unsafe.
Maybe f
would better be a template function:
template<typename T>
void f(T **array) {
...
}
The case is incorrect. Suppose the function is (perfectly legitimate):
void f(A** foo)
{
foo[0] = new A();
}
now if you passed a B** instead
, the first pointer (which the compiler is certain is a B*
) has suddenly become an A*
-- terrible type-violation, hard-crash likely soon.
A**
-- no const
in sight, please notice! -- means a mutable pointer to mutable pointers to A, which is why setting one of those pointers to a new pointer to A
is perfectly OK. But you can't do that if you actually have a B**
-- those pointers must always be to B
(or subclass thereof), not to A
, a superclass of B
.
Yep, it's covariance vs contra-variance all over again -- under mutability (no const
in sight), it's really a minefield. Why not stick in all the const
you can possibly afford? This will also indicate which casts make sense under which circumstances!
If B
is a subclass of A
then you can still sort a list of pointers to objects of type B
even if the type of the array is "array of pointers to A
".
E.g.
A** ptrToBs = new A*[10];
ptrToBs[0] = &b01; // ... or new B
ptrToBs[1] = &b02;
// ...
ptrToBs[9] = &b10;
f(ptrToBs);
However, what you say you want is a generic algorithm to swap objects, not pointers based on the value of the pointed-to objects. In this case, you are better off having a function template.
template< class T >
void f(T* t)
{
// ...
}
This way you can sort an array of A
or and array of B
without having to have an array of pointer to exactly the right type; you can just sort an array of A
or B
objects or anything else provided that the type of objects that you are sort support the operations that you are using in your sort algorithm.
Typically you would want to pass the size of the array or a pointer to the end of the array so that the algorithm doesn't have to assume how big the array is.
template< class T > void f(T* arr, std::size_t size);
or
template< class T > void f(T* first, T* last);
精彩评论