Проблемы с фабричным методом с общими указателями и ограниченными конструкторами - PullRequest
0 голосов
/ 03 мая 2018

Компилируется нормально, но выдает ошибку времени выполнения при вызове b->hello(). Я собираюсь использовать динамический тип указателя b и вызвать Inherited::hello() version.

Помощь :-)

#include <iostream>
#include <memory>

using namespace std;

class Base {
public:
    static  shared_ptr<Base> factory();
    string hello(){};
    virtual ~Base() {};

protected:
    Base(){};
};


class InheritedA : public Base{
friend class Base;
public:
    string hello() {return "I am iA";}
protected:
    InheritedA() {};
};


shared_ptr<Base> Base::factory() {
    shared_ptr<Base>        ptrB;
    shared_ptr<InheritedA>  ptrA;
    ptrA = shared_ptr<InheritedA>(new InheritedA);

    ptrB = dynamic_pointer_cast<Base>(ptrA);

    return ptrB;
};

int main() {

    shared_ptr<Base> b;
    b = Base::factory();


    cout << b->hello();
    return 0;
}

Ответы [ 2 ]

0 голосов
/ 03 мая 2018

Очевидно - virtual отсутствовало в Base::hello() декларации, также override после InheritedA::hello().

#include <iostream>
#include <memory>

using namespace std;

class Base {
public:
    static  shared_ptr<Base> factory();
    virtual string hello(){};
    virtual ~Base() {};

protected:
    Base(){};
};


class InheritedA : public Base{
friend class Base;
public:
    string hello() override {return "I am iA";}
protected:
    InheritedA() {};
};


shared_ptr<Base> Base::factory() {
    shared_ptr<Base>        ptrB;
    shared_ptr<InheritedA>  ptrA;
    ptrA = shared_ptr<InheritedA>(new InheritedA);
    //some very complex stuff here
    ptrB = dynamic_pointer_cast<Base>(ptrA);

    return ptrB;
};

int main() {

    shared_ptr<Base> b;
    b = Base::factory();


    cout << b->hello();
    return 0;
}
0 голосов
/ 03 мая 2018

Вы забываете одну очень важную вещь, когда дело доходит до полиморфизма и переопределения функций базового класса: функции должны быть virtual.

Поскольку ваша функция не virtual, вы вызываете функцию Base::hello, и, поскольку она ничего не возвращает, у вас будет неопределенное поведение , приводя к аварии, которую вы испытываете.

Вы можете попросить компилятор помочь вам обнаружить такие случаи, используя спецификатор override :

class InheritedA : public Base{
friend class Base;
public:
    string hello() override  // Tell the compiler that this function should
                             // override the function from the parent class
    {return "I am iA";}
protected:
    InheritedA() {};
};

Если вы используете спецификатор override, компилятор выдаст ошибку, если функция не virtual.

Помимо маркировки функции базового класса virtual, вам действительно нужно либо вернуть что-то, что-нибудь из функции, либо сделать ее абстрактной:

class Base {
public:
    static  shared_ptr<Base> factory();

    // Make the function a pure abstract function that must be overridden
    virtual string hello() = 0;

    virtual ~Base() {};

protected:
    Base(){};
};
...