Насколько я знаю, векторы не могут быть созданы во время выполнения! Должен быть xml-файл для использования векторов.
Объект тип Child *
не может быть привязан к Parent * &
по той же причине, по которой Child **
не может быть преобразован в Parent **
. Разрешение этого позволило бы программисту (преднамеренно или нет) нарушать безопасность типов без приведения.
class Animal {};
class DangerousShark : public Animal {};
class CuteKitten : public Animal {};
void f(Animal*& animalPtrRef, Animal* anotherAnimalPtr)
{
animalPtrRef = anotherAnimalPtr;
}
void g()
{
DangerousShark myPet;
CuteKitten* harmlessPetPtr;
f(harmlessPetPtr, &myPet); // Fortunately, an illegal function call.
}
Редактировать
Я думаю, что некоторая путаница возникает из-за свободного использования слов «конвертировать» и «преобразование».
Ссылки не могут быть восстановлены, в отличие от объектов, которые могут быть переназначены, поэтому в контексте ссылок, когда мы говорим о преобразовании, мы можем быть обеспокоены только инициализацией новой ссылки.
Ссылки всегда привязанный к объекту, и из вопроса ОП было ясно, что он стремится получить ссылку, которая является прямой связью с существующим объектом. Это допустимо только в том случае, если объект, использованный для инициализации ссылки, совместим с ссылками с типом ссылки. По сути, это только в том случае, если типы одинаковы или тип объекта определяется на основе типа ссылки, а тип ссылки, по крайней мере, такой же квалифицированный как cv, что и инициализирующий объект. В частности, указатели на разные типы не являются ссылочно-совместимыми, независимо от отношения указанных типов.
В других случаях ссылка может быть инициализирована чем-то, что может быть преобразовано в ссылочный тип. В этих случаях, однако, ссылка должна быть постоянной и не изменчивой, и преобразование создаст временный объект, и ссылка будет привязана к этому временному, а не к исходному объекту. Как уже указывалось, это не подходит для требований мотивирующего примера OP.
В итоге, Child
может быть напрямую связан с Parent &
, но Child *
не может быть напрямую связан с Parent * &
. Parent * const &
можно инициализировать с помощью Child *
,
У ваших классов нет виртуальной функции. См. FAQ 20.7
Beacuse Parent * &
- ссылка на указатель на объект Parent
. Вы передаете указатель на потомок
- это несовместимые типы. Вы можете привязать временную ссылку к const-ссылке, т. Е. Если вы измените свой параметр на:
void RemoveObj (Parent * const & foo);
Но тогда вы не сможете много с этим сделать.
Это был просто тестовый код, поэтому я не создавал виртуальных деструкторов. Если я правильно понимаю во втором вызове RemoveObj (), я получаю временный объект Parent *, который можно передать как постоянную ссылку на функцию. Это правильно?
Я настоятельно рекомендую вам запустить следующую программу в стандартном режиме C ++ 98, один раз как и затем снова после того, как вы закомментировали foo (b)
и раскомментировали delete b
. Затем попробуйте вставить виртуальный
перед ~ s ()
. Различия должны быть самоочевидными!
#include <iostream>
using namespace std;
struct s {
s() {cout << __func__ << endl; }
~s() {cout << __func__ << endl; }
};
struct t : s {
t() {cout << __func__ << endl; }
~t() {cout << __func__ << endl; }
};
void foo(s* const& x) { delete x; }
int main() {
t* b = new t;
foo(b);
//delete b;
}
type * & является другой синтаксической формой типа ** и Parent * & и Child * & не связаны друг с другом, так же как Parent ** и Child ** - это разные типы не в одной иерархии классов.
You can convert a Child* to a Parent*
: this creates a temporary. But you cannot bind a non-const reference to that temporary.
That's not a problem of **/*&/etc
. What you are trying to do is totally OK and makes sense. That Shark vs. Kitten has the same issue: not a matter of mixing kitten and sharks. You cannot bind a non-const reference to that unnamed pointer.
This is not the Parent** vs. Child**
problem: there, if a Child**
was a Parent**
, then one could assign p[0] = new NotAChild;
. A collection of objects which are all subtypes of A is not a collection of A.
Это не сработает по причинам, указанным Дирком. Если вам действительно нужен метод RemoveObj, я бы просто сохранил вновь выделенный дочерний объект как родительский *:
#include <iostream>
class Parent
{
public:
virtual ~Parent()
{
std::cout << "Parent destructor" << std::endl;
}
};
class Child : public Parent
{
public:
virtual ~Child()
{
std::cout << "Child destructor" << std::endl;
}
};
void RemoveObj(Parent*& pObj)
{
delete pObj;
pObj = NULL;
}
int main (int argc, const char * argv[]) {
Parent* pPObj = new Parent;
Parent* pCObj = new Child;
RemoveObj(pPObj);
RemoveObj(pCObj); // This is line 32
return 0;
}