Как вернуть действительный указатель в методе фабрики в производный класс на основе базовой ОС - PullRequest
1 голос
/ 29 января 2020

Я не могу вызвать частные методы производного класса, используя указатель на базовый класс, возвращенный методом Factory.

Я хотел бы вернуть unique_ptr для Cat, когда пользователь работает на WIN и unique_ptr собаке, когда пользователь работает на Linux.

Base.h чистый виртуальный класс

#include <iostream>
#include <memory>

class Base
{
public:
    virtual void echo() = 0;
};

Cat.h - производный класс База

#include "Base.h"

class Cat : public Base
{
public:
    void echo();
    void CatPrivateFunction();
};

Кат. cpp

#include "Cat.h"

void Cat::echo()
{
    std::cout << "In echo()" << std::endl;
}

void Cat::CatPrivateFunction()
{
    std::cout << "In CatPrivateFunction()" << std::endl;
}

Dog.h - производный класс Base

#include "Base.h"

class Dog
{
    void echo();
    void DogPrivateFunction();
};

Dog. cpp

#include "Dog.h"

void Dog::echo()
{
    std::cout << "In echo()" << std::endl;
}

void Dog::DogPrivateFunction()
{
    std::cout << "In DogPrivateFunction()" << std::endl;
}

BaseFactory.h

#ifdef _WIN32
#include "Cat.h"
#elif __linux__
#include "Dog.h"
#endif
#include <memory>

class BaseFactory
{
public:
    static std::unique_ptr<Base> createBase();
};

BaseFactory. cpp

#include "BaseFactory.h"

std::unique_ptr<Base> BaseFactory::createBase()
{
#ifdef __linux__
        return std::unique_ptr<Base>(new Dog{});
#elif _WIN32
        return std::unique_ptr<Base>(new Cat{});;
#endif
}

В следующем сценарии

#include "BaseFactory.h"
int main()
{
    std::unique_ptr<Base> p = BaseFactory::createBase();
    p->echo();
    p->CatPrivateFunction();
    return 0;
}

Я ожидаю следующий вывод

In echo ()
In CatPrivateFunction ()

Но p->CatPrivateFunction() не работает, так как Base.h не имеет CatPrivateFunction() функции-члена.

Как это можно сделать?

Ответы [ 2 ]

4 голосов
/ 29 января 2020

Пожалуйста, прочитайте о upcasting и downcasting .

Вам нужно downcast"указатель" на Base «на» указатель на Cat ».

Учитывая, что вы не знаете точный тип, на который указывает указатель, вам нужно использовать dynamic_cast и убедитесь, что результат не является нулевым указателем:

if (auto cat = dynamic_cast<Cat*>(p.get()))
    cat->CatPrivateFunction();
2 голосов
/ 29 января 2020

Вы не можете вызвать CatPrivateFunction() без действительного указателя / ссылки на Cat объект. Поскольку у вас есть только указатель на Base, вам придется использовать dynamic_cast, чтобы проверить, указывает ли этот указатель Base на Cat или нет, и если это так, то вы можете вызвать CatPrivateFunction() на нем Например:

#include "BaseFactory.h"
#include "Cat.h"

int main()
{
    std::unique_ptr<Base> p = BaseFactory::createBase();
    p->echo();
    Cat *c = dynamic_cast<Cat*>(p.get());
    if (c)
        c->CatPrivateFunction();
    return 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...