Приведение массива указателей на объекты - PullRequest
1 голос
/ 21 марта 2010

Если B является подклассом A.

А у меня в main():

B** b = new B*[10];
... // some algorithm that does b[i] = new B(..);

Итак, у меня есть массив указателей на объекты B.

Тогда у меня есть функция:

void f(A** foo);

Если в основном, я делаю: f(b); Я получаю предупреждение, но, очевидно, если я делаю: f((A**)b);, я не получаю.

(A**) это немного противно. Мне было интересно, есть ли в C ++ более элегантный способ, который по крайней мере делает проверку типов как dynamic_cast.

Я хочу, чтобы foo сортировал (только с использованием подкачки) массивы объектов типа A или подкласса ... поэтому создайте общий алгоритм сортировки. Надеюсь, теперь вы лучше понимаете мою проблему.

Ответы [ 4 ]

2 голосов
/ 21 марта 2010

Существует причина, по которой вы получаете предупреждение или ошибку, если пытаетесь неявно привести B** к A**: это небезопасно.

Ссылаясь на массив как A**позволяет помещать указатели на A объекты внутри.Для массива B* это неправильно, и, следовательно, приведение небезопасно.

Может быть, f лучше было бы использовать функцию шаблона:

template<typename T>
void f(T **array) {
   ...
}
2 голосов
/ 21 марта 2010

A** и B** - это два совершенно разных типа. То, что существует неявное преобразование из B* в A*, не означает, что такое же преобразование существует из B** в A**. См. Этот раздел часто задаваемых вопросов Преобразование производного * → База * работает нормально; почему Derived ** → Base ** не работает? для более подробной информации.

1 голос
/ 21 марта 2010

Дело неверное.Предположим, что функция (совершенно законная):

void f(A** foo)
{
  foo[0] = new A();
}

Теперь, если вы передали B** instead, первый указатель (который, как уверен компилятор, B*) внезапно стал A* -- ужасное нарушение шрифта, возможен тяжелый сбой в ближайшее время.

A** - нет const в поле зрения, пожалуйста, обратите внимание!- означает изменяемый указатель на изменяемый указатель на A, поэтому установка одного из этих указателей на новый указатель на A совершенно нормально.Но вы не можете этого сделать, если у вас действительно есть B** - эти указатели должны всегда равны B (или подкласс их), не до A, суперкласс из B.

Да, это снова ковариантность и противоречивость - при изменчивости (нет * 1032)* в поле зрения), это действительно минное поле.Почему бы не придерживаться всех const, которые вы можете себе позволить?Это также укажет, какие броски имеют смысл при каких обстоятельствах!

0 голосов
/ 21 марта 2010

Если B является подклассом A, то вы все равно можете отсортировать список указателей на объекты типа B, даже если тип массива - «массив указателей на A».

1007 * Е.Г. *

A** ptrToBs = new A*[10];

ptrToBs[0] = &b01; // ... or new B
ptrToBs[1] = &b02;

// ...

ptrToBs[9] = &b10;

f(ptrToBs);

Однако то, что вы говорите , вы хотите - это общий алгоритм для обмена объектами, а не указатели, основанные на значении указанных объектов. В этом случае вам лучше иметь шаблон функции.

template< class T >
void f(T* t)
{
    // ...
}

Таким образом, вы можете отсортировать массив A или массив B без необходимости иметь массив указателей на правильный тип; Вы можете просто отсортировать массив объектов A или B или что-либо еще, при условии, что тип сортируемых объектов поддерживает операции, которые вы используете в алгоритме сортировки.

Как правило, вы хотите передать размер массива или указатель в конец массива, чтобы алгоритм не предполагал, насколько велик массив.

template< class T > void f(T* arr, std::size_t size);

или

template< class T > void f(T* first, T* last);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...