Доступ к защищенным функциям членства из тестового кода в C++

Не упустите упаковку проблем. В примере Вы дали все поля, при очевидных смещениях, потому что все находится на 4-байтовых границах, но это будет не всегда иметь место. Visual C++ упаковывает на 8-байтовых границах по умолчанию.

11
задан Community 23 May 2017 в 11:45
поделиться

8 ответов

Хорошо, поскольку вы сказали, что это всего лишь тестовый код, я собираюсь предложить что-то серьезное хакерское, но оно сработает:

struct tc : protected Foo
{
    tc(Foo *foo, Data& data)
    {
        ((tc*)foo)->DoSomething(data);
    }
};

Blah blah;
tc t(&blah.foo, blah.data);
8
ответ дан 3 December 2019 в 01:16
поделиться

Есть способ, который полностью разрешен Стандартом.

//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);

Прочтите статью Скрытые возможности C ++ для объяснения.


Вы можете написать макрос для вашего удобства (круглые скобки здесь, чтобы вы могли использовать этот макрос также для типов, которые имеют запятую, например vector > ):

#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);
17
ответ дан 3 December 2019 в 01:16
поделиться

С одной стороны, не делайте этого .

С другой стороны, вот игра:

#define protected public
#include "foo.h"
#undef protected

8 -)

А если серьезно, почему DoSomething () защищен? Наверное, потому, что вызов из внешнего кода может что-то сломать. В этом случае не следует вызывать его из тестов.

7
ответ дан 3 December 2019 в 01:16
поделиться

Я сделал

class Foo
{
protected:
    void DoSomething(Data data);
public:
    #ifdef TEST
    void testDoSomething(Data data);
    #endif
}

Затем скомпилируйте ваши модульные тесты с помощью g ++ -D TEST.

3
ответ дан 3 December 2019 в 01:16
поделиться

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

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

РЕДАКТИРОВАТЬ: Вы рассматривали возможность наследования тестового класса от реального класса?

3
ответ дан 3 December 2019 в 01:16
поделиться

Используйте оболочку следующим образом:

// 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's no problem!    
}
2
ответ дан 3 December 2019 в 01:16
поделиться

Вы можете использовать наследование с функциями пересылки:

class Foo
{
protected:
    void DoSomething(Data data);
}

class test_Foo : public Foo
{
public:
    void testDoSomething(Data data)
    {
        DoSomething(data);
    }
}
2
ответ дан 3 December 2019 в 01:16
поделиться

Если это строго тестовый код, вы можете сделать ...

#define protected public
#include "Foo.h"

// test code

#undef protected
1
ответ дан 3 December 2019 в 01:16
поделиться
Другие вопросы по тегам:

Похожие вопросы: