Преобразование из полученного* к Base*&

Насколько я знаю, векторы не могут быть созданы во время выполнения! Должен быть xml-файл для использования векторов.

6
задан Community 23 May 2017 в 11:47
поделиться

5 ответов

Объект тип 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 * ,

7
ответ дан 9 December 2019 в 20:48
поделиться
  • У ваших классов нет виртуальной функции. См. 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;
}
4
ответ дан 9 December 2019 в 20:48
поделиться

type * & является другой синтаксической формой типа ** и Parent * & и Child * & не связаны друг с другом, так же как Parent ** и Child ** - это разные типы не в одной иерархии классов.

0
ответ дан 9 December 2019 в 20:48
поделиться

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.

1
ответ дан 9 December 2019 в 20:48
поделиться

Это не сработает по причинам, указанным Дирком. Если вам действительно нужен метод 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;
}
0
ответ дан 9 December 2019 в 20:48
поделиться
Другие вопросы по тегам:

Похожие вопросы: