2010-06-04 21 views
2

Une partie de notre système utilise la mémoire partagée entre les processus qui ne partagent pas un ancêtre commun. Nous plaçons des objets C++ dans cette mémoire partagée. Les méthodes sur ces objets sont soit en ligne dans les en-têtes, soit hors ligne dans les bibliothèques d'objets qui sont liées aux processus respectifs.De toute façon en C++ pour une classe de base pour interdire les méthodes virtuelles dans toutes les classes dérivées?

Une erreur fréquemment faite par les nouveaux venus dans le système est d'introduire une méthode virtuelle quelque part. Ceci est garanti pour planter le système car il n'y a aucun moyen de s'assurer que le VT (table virtuelle) réside à la même adresse dans chaque processus.

Je me demande donc s'il existe un moyen pour que le compilateur génère une erreur si quelqu'un tente d'introduire une méthode virtuelle. Quelque chose de similaire à rendre les constructeurs de copie et d'affectation privés pour interdire la sémantique de la copie.

+7

La réponse n'est pas de placer des objets C++ dans la mémoire partagée - cela se termine toujours en larmes. Mettez les données brutes dans la mémoire partagée - pas les objets. –

+2

@Neil - Mais Boost.Interprocess est tellement cool ... –

+0

@Neil - c'est un "jetons le bébé avec l'eau du bain" attitude.La révocation du polymorphisme basé sur VT ne rend pas les objets C++ inutiles. Et le coût d'avoir à enseigner à un débutant les implications de la mémoire partagée pâlit devant la complexité supplémentaire que nous aurions à supporter pour n'avoir que des données brutes dans la mémoire partagée. –

Répondre

1

Vous pourriez #define virtual Something_else qui donnerait des erreurs de compilateur quand quelqu'un a utilisé virtuel, mais ils n'auraient aucun sens sans un peu plus de travail. Boost.TypeTraits offre un trait is_polymorphic, mais vous devrez peut-être faire quelques trucs pour l'appliquer partout où vous en avez besoin.

+1

Solution Win. '#define virtual void échec() {static_assert (false," Aucune fonction virtuelle autorisée! ");}' – Puppy

+2

Compteur: '#undef virtual' – Dashogun

3

(Par exemple, appeler le is_polymorphic sur une classe de base ne vous indiquera pas si une classe dérivée a introduit une fonction virtuelle.)

Selon votre système de construction et les outils disponibles, vous pouvez y introduire des contrôles. Par exemple, si je lance nm -C sur un fichier objet créé par GCC, je vois la sortie suivante pour une classe de test simple avec des fonctions virtuelles:

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

que je puisse mettre mon makefile (ou autre) pour exécuter nm -C sur tous les fichiers objets et déclencher une erreur, le cas échéant contenir vtable for.

4

Lors de la validation à votre dépôt,
Pour chaque classe partagée de cette manière,
si le mot apparaît virtuel dans le fichier
échouent à l'commettras, envoyez un courriel à un développeur senior, et d'un quai le salaire du partie fautive.

4

GCC (et peut-être d'autres) donne un avertissement lorsqu'une fonction virtuelle apparaît dans une classe avec un destructeur non virtuel.

Donnez à toutes vos classes partagées un destructeur non virtuel explicite (ne faites rien?) Et traitez les avertissements comme des erreurs.

+0

Bien que cela n'empêche pas un développeur débutant d'ajouter son propre destructeur virtuel .. –

+0

Un débutant pourrait changer le destructeur de classe de base en virtuel - vous avez besoin d'un! COMMENTAIRE! Là. Il n'a pas pu ajouter un destructeur virtuel à une classe dérivée sans déclencher le même avertissement. – Arkadiy

+0

J'ai fait un test rapide, et il semble que l'ajout d'un destructeur virtuel à une classe dérivée ne déclenche pas d'avertissement, au moins pour GCC 4.3.2. Ce serait une pratique étrange, cependant, alors vous avez raison, un! devrait arrêter la plupart des abus. –

2

Vous pouvez utiliser is_polymorphic est la combinaison avec BOOST_STATIC_ASSERT pour créer une erreur de compilateur lorsque quelqu'un ajoute une fonction virtuelle à une classe. Placez l'appel BOOST_STATIC_ASSERT dans le fichier d'implémentation de votre classe.

#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); 
} 
0

Il s'agit d'une réponse (Visual Studio 2015) C++ 11 à une ancienne question. C'est similaire à la réponse Boost.

#include <type_traits> 

class foo 
{ 
}; 

static_assert(!std::is_polymorphic<foo>::value, "Virtual not allowed in this class.");