Не удается получить переопределенный метод в производном классе (googlemock-fixture) с возвратом к базовому классу fixture для работы

#c

#c

Вопрос:

Я довольно новичок в C , больше привык к C и python, но на этот раз Google не был моим другом.

У меня есть базовый класс, который реализует некоторые приспособления googlemock, реализованные в 2 универсальных классах (базовый класс и параметризованный класс, который является производным от этого базового класса), и функция TEST_P, использующая параметризованный прибор. Поскольку параметризованный инструмент используется для тестирования двух реализаций, я поместил классы fixture и TEST_P в cpp-файл базового класса ( hpp-файл), а конкретные таблицы параметров — в 2 конкретных cpp-файла. Это работает как шарм.

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

Итак, я хочу переопределить общую реализацию только для 1 из 2 тестовых файлов cpp.

Изначально (без переопределения) У меня было следующее в hpp:

 class MyBaseClass : public ::testing::Test
{
    protected:
       // boring fixture setup stuff
       virtual void test( void );
}

class MyParametrizedBaseClass:
    public MyBaseClass, 
    public::testing::WithParmInterface< std:tr1::tuple< /* parameter definition */ > >{
    protected:
        // some custom assert method definitions
}
  

baseclass.cpp файл:

 MyBaseClass::test( void )
{
    cout << "This is the baseclass implementation" << std::endl;
}

...

TEST_P( MyParametrizedBaseClass, TestName )
{
     test();
     // other googlemock checks not needed for this question
}
  

И в двух конкретных реализациях у меня есть только таблицы параметров:

 std:tr1::tuple< /* parameter definition */ > const TableName[] = {
    //table implementation
}

INSTANTIATE_TEST_CASE_P( Name, MyParameterizedBaseClass, ::testing::ValuesIn( TableName ) );
  

Опять же, до сих пор это работает.

Теперь для … давайте назовем это impl_1 … мы хотим, чтобы тест выполнял следующее (этот код не работает, поскольку определение для MyParameterizedBaseClass::test не найдено):

impl_1.cpp:

 void MyParameterizedBaseClass::test( void )
{
    cout << "This is the impl_1 implementation" << std::endl;
}
  

Первое, что я сделал, увидев, что компилятор пропускает определение MyParameterizedBaseClass ::test, это заменил MyParameterizedBaseClass на MyBaseClass , но затем он рассматривает это как переопределение (которым оно действительно является).

Итак, затем я погуглил и нашел ключевое слово ‘override’ и адаптировал определение MyParameterizedBaseClass, чтобы оно выглядело следующим образом:

 class MyParametrizedBaseClass:
    public MyBaseClass, 
    public::testing::WithParmInterface< std:tr1::tuple< /* parameter definition */ > >{
    protected:
        // some custom assert method definitions
        void test( void ) override;
}
  

Но когда я это делаю, я получаю ошибку:
Baseclass.hpp: [номер строки]: ожидаемая ошибка ‘;’ перед ‘переопределением’
И в конкретной реализации для impl_1 все еще говорится, что в MyParameterizedBaseClass не объявлена тестовая функция

И если я (заранее зная, что это неправильно) поставлю ‘;’ перед ‘override’, как было предложено, я получаю: ошибка: ISO C запрещает объявление ‘override’ без типа

Затем я удалил ключевое слово ‘override’ и перекомпилировал. Теперь компилятор удовлетворен, но компоновщик завершается ошибкой на impl_2, поскольку там у меня нет реализации MyParameterizedClass::test. И это правда, поскольку я хочу иметь реализацию test по умолчанию для этого. (Для завершения описания: Да, это снова работает, если я также реализую test для MyParameterizedBaseClass в impl_2.cpp )

Итак, мой вопрос: что я делаю не так?

Среда: Linux с GCC 4.4.2 (довольно старая, я знаю, но это версия, которая есть у моей компании)

Ответ №1:

Добавление объявления в MyParametrizedBaseClass было хорошим ходом. Проблема в том, что вы использовали функцию C 11 override и основываетесь на коде, подобном этому:

 std:tr1::tuple< /* parameter definition */ >
  

( tr1 ) указывает, что вы используете C 03 с «техническим отчетом один», поэтому ключевое слово override неизвестно. Вот почему компилятор жалуется: error: expected ';' before 'override'

Поэтому просто удалите override ключевое слово, и все должно быть в порядке.

Комментарии:

1. Я попробовал это, и компилятору это понравилось. Но компоновщик этого не делает, поскольку в этом случае он пропускает реализацию test MyParemeterizedBaseClass для реализации, которая все еще должна использовать реализацию по умолчанию (impl_2.cpp )

2. у вас есть определение void MyParameterizedBaseClass::test( void ) ? Если да, и у вас все еще есть проблема с компоновщиком, выполните перестройку или очистку перед сборкой.

3. В заголовке у меня теперь есть это. Я попробую выполнить чистую сборку.

4. По-прежнему происходит сбой компоновщика (который, вероятно, тоже старый, зная мою компанию). Вероятно, я вынужден реализовать MyParameterizedBaseClass::test для impl_2.cpp также и пусть эта реализация вызывает реализацию MyBaseClass. Недостатком этого является то, что всякий раз, когда возникает impl_3.cpp мы вынуждены к этой реализации <грустное лицо>. @MarekR: спасибо за вашу помощь.

5. In the header I now have that. это проблема. У вас не может быть такого рода определений методов в заголовках (есть некоторые исключения). Это закончится проблемой двойного определения компоновщика.