Наследование C ++ и включает

Я не новичок в C ++, но я точно не эксперт ... пока :)

Пытаюсь понять, как работает наследование. У меня есть класс, производный от базового класса:

class Base {}

и

#include "Base.h"
class Derived : public Base {}

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

#include "Derived.h"
class Base {
     static Derived* getDerived();
}

Теперь я подумал, что, поскольку это статический член, мне, возможно, сойдет с рук, но я получаю проблемы во время компиляции, жалуясь, что класс Derived не знает, что такое объект Base, хотя я включаю Base.h в Производный класс. Я также знаю о круговой зависимости, однако, поскольку я пытаюсь вернуть указатель на объект, я полагал, что компилятору не понадобится #include "Derived.h", но похоже, что это так.

Любые указания о том, почему это не тот путь, и что я мог бы сделать вместо этого, были бы очень признательны!

(Сейчас я делаю это на Java)


person ossys    schedule 02.04.2015    source источник
comment
почему ты хочешь сделать это? Разве базовому классу не нужно ничего знать о производных типах?   -  person James Adkison    schedule 02.04.2015
comment
Я согласен с @JamesAdkison здесь, реальный вопрос в том, зачем вам вообще это нужно. Мне кажется, это запах кода.   -  person MahlerFive    schedule 02.04.2015
comment
Я согласен, это не похоже на хороший дизайн. Наш текущий вариант использования - это реализация модели данных. И поскольку это статический метод, который возвращает производный класс, базовый класс в основном действует как фабрика для создания производного типа. Мы могли бы разместить фабрику в другом месте, но с точки зрения API это очень чисто, и это единственная причина, по которой мы решили реализовать такой способ.   -  person ossys    schedule 02.04.2015


Ответы (3)


Да, в вашем случае (просто верните указатель на объект) компилятору не понадобится #include "Derived.h", ему просто нужен предварительное объявление:

class Derived;
class Base {
     static Derived* getDerived();
};

ДЕМО: http://ideone.com/ONUHGc

person songyuanyao    schedule 02.04.2015
comment
Да, форвардная декларация - это то, что нам нужно в этом случае, спасибо! В настоящее время мы работаем над тем, чтобы реализовать это лучше, чем чтобы базовый класс возвращал объект производного класса. - person ossys; 02.04.2015

Следующий код отвечает на ваш вопрос, но я вообще не знаю, зачем вам это нужно.

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

Base.h

#ifndef BASE_H
#define BASE_H

class Derived; // Forward declaration to avoid including 'Derived.h'

class Base
{
public:
    virtual ~Base() {}

    // Non-static function so that it has access to 'this'
    Derived* getDerived();
};

#endif

Base.cpp

#include "Base.h"

#include "Derived.h"

Derived* Base::getDerived()
{
    return dynamic_cast<Derived*>(this);
}

Derived.h

#ifndef DERIVED_H
#define DERIVED_H

#include "Base.h"

class Derived : public Base
{
public:
    virtual ~Derived() override {}
};

#endif

main.cpp

#include "Derived.h"

#include <iostream>

int main()
{
    Derived d;
    Base* b = &d;

    std::cout << &d << " : " << b->getDerived() << "\n";

    return 0;
}
person James Adkison    schedule 02.04.2015
comment
Абсолютно согласен, что это странно, но с точки зрения API он предлагает очень чистый API для конечного пользователя. В настоящее время мы ищем другие способы реализовать это без того, чтобы базовый класс возвращал указатель на экземпляр производного класса. - person ossys; 02.04.2015

Это Циркулярные ссылки.

  1. Чтобы использовать Class-Base, вам необходимо знать Class-Derived, потому что он содержит статическую функцию с возвращаемым типом Class-Derived.

  2. Чтобы использовать Class-Derived, вам необходимо знать Class-Base, потому что он является производным от Class-Base

person banyudu    schedule 02.04.2015