реализация абстрактной функции базового класса в другом шаблонном базовом классе - PullRequest
0 голосов
/ 14 декабря 2010

У меня есть проект Visual Studio 2008 C ++, где у меня есть класс, который наследуется от абстрактного базового класса, и другой шаблонный класс, который реализует функцию в абстрактном базовом классе.Например:

class Foo;

struct Buzz
{
    virtual ~Buzz() {};
    virtual void Buzz_Do( Foo* ) = 0;
};

class Base
{
public:
    virtual ~Base() {};
    virtual void Base_Do( Buzz* ) = 0;
};

template< class T >
class Bar
{
public:
    virtual void Base_Do( Buzz* v )
    {
        v->Buzz_Do( static_cast< T* >( this ) );
    };
};

class Foo : public Base, public Bar< Foo >
{
};

int _tmain(int argc, _TCHAR* argv[])
{
    Foo c;
    return 0;
}

К сожалению, это приводит к ошибке компилятора:

1>MyApp.cpp(39) : error C2259: 'Foo' : cannot instantiate abstract class
1>        due to following members:
1>        'void Base::Base_Do(Buzz *)' : is abstract
1>        MyApp.cpp(17) : see declaration of 'Base::Base_Do'

Я пытался добавить публичную using Bar< Foo >::Base_Do; к class Foo, но это не помогло.

Есть ли способ сделать эту работу, или мне нужно будет поместить конкретную Base_Do() реализацию в Foo и не использовать Bar<>?

Спасибо, PaulH

Ответы [ 7 ]

4 голосов
/ 14 декабря 2010

Если возможно, пусть Bar<> происходит от Base, и Foo происходят только от Bar<T>.

2 голосов
/ 14 декабря 2010

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

То, что вы делаете, сильно зависит от вашей проблемы. Я обычно предпочитаю первое, но сталкивался с ситуациями, когда это невозможно (поскольку нужные мне базы просто не связаны), и использую второе.

2 голосов
/ 14 декабря 2010

Насколько может сказать компилятор, ваша шаблонная функция не фактически реализует функцию из базового класса. Компилятор считает, что Base::Base_Do и Bar<T>::Base_Do - это две совершенно не связанные функции, а НЕ реализация одной.

То, что видит компилятор, состоит в том, что Foo в результате имеет две функции (почти) с одинаковыми именами: Base::Base_Do и Bar<T>::Base_Do. Bar вообще не реализует интерфейс Base.

Я думаю, что вы действительно хотите, чтобы Bar<T> унаследовал от Base и реализовал Base_Do. Тогда Foo наследуется только от Bar<Foo>.

Но, несмотря на все это, можете ли вы сказать нам более четко, какую проблему вы на самом деле пытаетесь решить ? Тогда мы можем предложить совет, как решить это. Отношения между Buzz и Foo и Foo до Bar и Base меня смущают.

EDIT: Также см. http://www.parashift.com/c++-faq-lite/multiple-inheritance.html#faq-25.10, поскольку это может предложить альтернативный механизм, который все еще позволяет использовать миксин.

1 голос
/ 14 декабря 2010

Вы пробовали:

template< class T , class K>

class Bar: public K
{
public:
    virtual void Base_Do( Buzz* v )
    {
        v->Buzz_Do( static_cast< T* >( this ) );
    };
};

class Foo : public Bar< Foo, Base >
{
};

Foo производный от Base, который имеет неопределенный виртуальный метод.Вы можете сделать это так, как я написал, или сделать вывод virtual.

0 голосов
/ 14 декабря 2010

У меня есть Visual Studio 2008 C ++ проект, где у меня есть класс, который наследует от виртуального базового класса и другой шаблонный класс, который реализует функция в виртуальном базовом классе.

  • Неверно: в вашем коде нет виртуальных базовых классов.

Вот ваш код (как я пишу это):

class Foo;

struct Buzz
{
    virtual ~Buzz() {};
    virtual void Buzz_Do( Foo* ) = 0;
};

class Base
{
public:
    virtual ~Base() {};
    virtual void Base_Do( Buzz* ) = 0;
};

template< class T >
class Bar
{
public:
    virtual void Base_Do( Buzz* v )
    {
        v->Buzz_Do( static_cast< T* >( this ) );
    };
};

class Foo : public Base, public Bar< Foo >
{
};

int _tmain(int argc, _TCHAR* argv[])
{
    Foo c;
    return 0;
}

Далее

  • Неправильно: функция чистого виртуального члена Buzz_Do нигде не реализована.

  • Неверно: в вашем коде отсутствует функция main (хотя, я думаю, читатели могли бы ее предоставить).

  • Неверно: макрос (или тип) _TCHAR нигде не определен.

Сказав это, виртуальное наследство & ndash; который вы утверждаете, что ваш фактический код использует & ndash; один из возможных ответов на вопрос, который, по-видимому, вы намеревались задать.

Однако с вашим неверно представленным кодом и неверными утверждениями об этом коде мало что можно сказать разумно. Я отмечаю, что другие все равно пытались. Возможно, если вам повезет, один из этих ответов будет отвечать всем требованиям, но это всего лишь азартная игра.

Приветствия и hth.,

0 голосов
/ 14 декабря 2010

Посмотрите на ошибку:

> 1>MyApp.cpp(39) : error C2259: 'Foo' :
> cannot instantiate abstract class 1>  
> due to following members: 1>       
> 'void Base::Base_Do(Buzz *)' : is
> abstract 1>        MyApp.cpp(17) : see
> declaration of 'Base::Base_Do'

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

0 голосов
/ 14 декабря 2010

Поскольку Foo расширяет Base, прежде чем создавать экземпляр Foo (Foo c;), вам необходимо реализовать все виртуальные методы Base.В вашем примере вам нужно реализовать virtual void Base_Do( Buzz* ).

...