Любой способ в C ++ для базового класса для набора виртуальных методов во всех производных классах? - PullRequest
2 голосов
/ 04 июня 2010

Часть нашей системы использует память, разделяемую между процессами, которые не имеют общего предка. Мы помещаем объекты C ++ в эту общую память. Методы для этих объектов являются либо встроенными в заголовках, либо внешними в библиотеках объектов, которые связаны с соответствующими процессами.

Ошибка, часто совершаемая новичками в системе, заключается в том, чтобы где-то ввести виртуальный метод. Это гарантированно приведет к сбою системы, поскольку нет способа гарантировать, что VT (виртуальная таблица) находится по одному и тому же адресу в каждом процессе.

Таким образом, мне интересно, есть ли способ заставить меня выдать ошибку компилятору, если кто-то попытается внедрить виртуальный метод. Что-то похожее на закрытие конструкторов копирования и присваивания для запрета семантики копирования.

Ответы [ 7 ]

4 голосов
/ 04 июня 2010

GCC (и может быть другим) выдает предупреждение, когда виртуальная функция обнаруживается в классе с не виртуальным деструктором.

Дайте всем вашим общим классам явный не виртуальный деструктор (ничего не делая?) И обрабатывайте предупреждения как ошибки.

4 голосов
/ 04 июня 2010

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

3 голосов
/ 04 июня 2010

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

В зависимости от вашей системы сборки и доступных инструментов, вы можете ввести там проверки. Например, если я запускаю nm -C в объектном файле, созданном GCC, я вижу следующий вывод для простого тестового класса с виртуальными функциями:

0000000e T TestMe::TestMe()
00000078 T TestMe::~TestMe()
00000000 V typeinfo for TestMe
00000000 V typeinfo name for TestMe
00000000 V vtable for TestMe

Таким образом, я могу настроить свой make-файл (или любой другой) для запуска nm -C на всех объектных файлах и выдавать ошибку, если они содержат vtable for.

2 голосов
/ 04 июня 2010

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

#include <boost/type_traits/is_polymorphic.hpp>
#include <boost/static_assert.hpp>
#include <cassert>

class A
{
public:
    /*virtual*/ void magic() {};    // making this virtual causes a compile error and a runtime error
};

using namespace boost;
int main()
{
    assert( is_polymorphic<A>::value == false );
    BOOST_STATIC_ASSERT( is_polymorphic<A>::value == false );
}
2 голосов
/ 04 июня 2010

Чтобы проверить, есть ли у класса виртуальный метод, вы можете использовать boost::is_polymorphic.

1 голос
/ 04 июня 2010

Вы могли бы #define virtual Something_else, что приводило бы к ошибкам компилятора, когда кто-либо использовал виртуальный, но они не имели бы никакого смысла без дополнительной работы.

0 голосов
/ 29 января 2016

Это (Visual Studio 2015) C ++ 11 ответ на старый вопрос. Это похоже на ответ Boost.

#include <type_traits>

class foo
{
};

static_assert(!std::is_polymorphic<foo>::value, "Virtual not allowed in this class.");
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...