Проблемы наследования с шаблонными классами - PullRequest
0 голосов
/ 09 марта 2009

Может кто-нибудь найти хороший способ заставить следующий код работать? (Это, опять же, невероятно упрощенный способ сделать это)

<code></p>

<p>template <class f, class g> class Ptr;</p>

<p>class RealBase
{
};</p>

<p>template <class a, class b, class c = Ptr<a,b> >
class Base : public RealBase
{
public:
    Base(){};
};</p>

<p>template <class d, class e>
class Derived : public Base <d,e>
{
public:
    Derived(){};
    void DerivedMethod(){};
};
template <class f, class g>
class Ptr
{
public:
    Ptr(){};
    Ptr(Base<f,g,Ptr<f,g> >* a){in = a;};
    Base<f,g,Ptr<f,g> >* operator->()
    {
        return in;
    };
private:
    Base<f,g,Ptr<f,g> >* in;
};</p>

<p>typedef Derived<double,double> DDerived;</p>

<p>int main()
{
    Base<int,int> b = Base<int,int>();
    Derived<double,double> d = Derived<double,double>();
    DDerived dd = DDerived();
    Ptr<double,double> p(&dd);
    p->DerivedMethod();
    return 1;
}

В данный момент компилятор стонет, потому что у Base <> нет DerivedMethod ();

EDIT

Я действительно понимаю проблему здесь, мой плохой из-за отсутствия объяснения в первом случае (я спешил). [Между прочим, это очень урезанный код, так что, ради простоты, у меня нет деструкторов или методов, которые действительно что-то делают. Просто игнорируйте это, это не имеет значения для проблемы.]

Что мне нужно сделать, так это то, что итератору (который здесь не описан), который имеет дело только с производным классом (D_Derived), необходим доступ к методу, который содержится в производном классе, а не в базовом классе. Простое добавление этого метода в базовый класс на самом деле не вариант, потому что эта ошибка произойдет много, если мне придется это сделать. (Существует около 10 классов, построенных на реальном базовом классе, и все они имеют свои собственные методы. Примерно 20 из них. Каждый.)

Кто-нибудь может придумать другой способ достижения этой функциональности?

Ответы [ 5 ]

2 голосов
/ 09 марта 2009

Этот код не работает, потому что класс шаблона Ptr возвращает объект класса базового шаблона, а не класса производного шаблона. Производный метод является частью производного шаблона, поэтому он генерирует ошибку компиляции. Принимая во внимание, что если DerivedMethod был частью базового шаблона, этот код будет работать

1 голос
/ 09 марта 2009

Очень сложно понять, чего вы на самом деле хотите достичь, используя ваш абстрактный класс и имена членов. Если вам действительно нужно обрабатывать указатель в Ptr как D_Derived, добавьте элемент доступа к Ptr и используйте приведение типа:

class Ptr {
    ...

    Base<f,g,Ptr<f,g> >* get() {
        return in;
    }
};

...

D_Derived* ptr = dynamic_cast<D_Derived*>(p.get());
if (ptr) {
    ptr->DerivedMethod();
}

РЕДАКТИРОВАТЬ : Как указал Конрад Рудольф, чтобы использовать динамическое приведение, вам необходимо добавить виртуальный метод в базовый класс.

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

class RealBase {
public:
    virtual ~RealBase() {}
};
1 голос
/ 09 марта 2009

Компилятор прав. Чтобы вы могли получить доступ к методу, этот метод должен быть объявлен в типе, который видит компилятор (это называется статический тип переменной). В вашем случае этот тип Base<…>, и компилятор не имеет ни малейшего представления, что это что-то еще.

1 голос
/ 09 марта 2009

Это имеет смысл. База не имеет такого метода (DerivedMethod). Если бы DerivedMethod был виртуальной функцией (может быть pure) базового класса, он бы работал.

0 голосов
/ 09 марта 2009

OK. Попробовав около 10 различных методов (static_cast, reinterpret_cast и т. Д.), Вы можете просто разыграть его.

int main()
{
    Base&lt;int,int> b = Base&lt;int,int>();
    Derived&lt;double,double> d = Derived&lt;double,double>();
    DDerived dd = DDerived();
    Ptr&lt;double,double> p(&dd);
    DDerived * fauxpointer;
    fauxpointer = (DDerived\*) &(*p);
    fauxpointer->DerivedMethod();
    return 1;
}

Насти. Но это работает, и это все, что имеет значение.

Приветствую всех, кто повторил вопрос мне.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...