Доступ к защищенным функциям-членам из тестового кода в С++
Я пытаюсь думать о лучшем способе доступа к защищенной функции-члену из некоторого тестового кода на С++, вот моя проблема:
//in Foo.h
Class Foo
{
protected:
void DoSomething(Data data);
}
//in Blah.h
Class Blah
{
public:
Foo foo;
Data data;
};
//in test code...
Blah blah;
blah.foo.DoSomething(blah.data); // Here my problem!
Некоторые возможные решения:
Сделайте класс тестового кода другом Foo, но это загрязняет Foo с помощью тестового кода
Сделать DoSomething общедоступной функцией
Я посмотрел на создание тестовой оболочки для Foo, как указано в
этом сообщении, однако это не сработает, поскольку Blah содержит экземпляр Foo.
Все советы/понимание/мнения приветствуются!
Спасибо
Ответы
Ответ 1
Хорошо, поскольку вы сказали, что это всего лишь тестовый код, я собираюсь предложить что-то серьезно взломанное, но будет работать:
struct tc : protected Foo
{
tc(Foo *foo, Data& data)
{
((tc*)foo)->DoSomething(data);
}
};
Blah blah;
tc t(&blah.foo, blah.data);
Ответ 2
Существует способ, который полностью разрешен Стандартом.
//in Foo.h
class Foo
{
protected:
void DoSomething(Data data);
};
//in Blah.h
class Blah
{
public:
Foo foo;
Data data;
};
//in test code...
struct FooExposer : Foo {
using Foo::DoSomething;
};
Blah blah;
(blah.foo.*&FooExposer::DoSomething)(blah.data);
Прочтите описание Скрытые функции С++ для объяснения.
Вы можете написать макрос для вашего удобства (скобки там, чтобы вы могли использовать этот макрос также для типов с запятой, например vector<pair<A, B>>
):
#define ACCESS(A, M, N) struct N : get_a1<void A>::type { using get_a1<void A>::type::M; }
template<typename T> struct get_a1;
template<typename R, typename A1> struct get_a1<R(A1)> { typedef A1 type; };
Теперь вопрос становится
ACCESS((Foo), DoSomething, GetDoSomething);
Blah blah;
(blah.foo.*&GetDoSomething::DoSomething)(blah.data);
Ответ 3
С одной стороны, не делают этого.
С другой стороны, здесь азартная игра:
#define protected public
#include "foo.h"
#undef protected
8 -)
Но серьезно, почему защита DoSomething()
защищена? Вероятно, потому что вызов его из внешнего кода может что-то сломать. В этом случае вы не должны вызывать его из своих тестов.
Ответ 4
Я сделал
class Foo
{
protected:
void DoSomething(Data data);
public:
#ifdef TEST
void testDoSomething(Data data);
#endif
}
Затем скомпилируйте свои модульные тесты с помощью g++ -D TEST.
Ответ 5
Вместо ifdefing private
to public
, рассмотрите ifdefing дружбу или еще лучше подумайте, действительно ли эта функция должна принадлежать этому классу, возможно, было бы достаточно иметь что-то в названии /unnamed namespace в cpp, а затем объявлено в тестовом проекте.
В любом случае, проверьте эту ссылку, возможно, ваша структура тестирования обеспечит аналогичную функциональность.
РЕДАКТИРОВАТЬ: Вы считали наследование своего тестового класса из своего реального класса?
Ответ 6
Вы можете использовать наследование с функциями пересылки:
class Foo
{
protected:
void DoSomething(Data data);
}
class test_Foo : public Foo
{
public:
void testDoSomething(Data data)
{
DoSomething(data);
}
}
Ответ 7
Используйте обертку следующим образом:
// Foo.h unchanged
// Blah.h unchanged
// test code
class FooTest : public Foo { friend void test(); }; // make friends
void test()
{
Blah blah;
static_cast<FooTest*>(&blah.foo)->DoSomething(blah.data); // Here no problem!
}
Ответ 8
Если это строго тестовый код, вы можете сделать...
#define protected public
#include "Foo.h"
// test code
#undef protected