Voici ce que je veux dire:
class MyClass {
int arr1[100];
int arr2[100];
int len = 100;
void add(int* x1, int* x2, int size) {
for (int i = 0; i < size; i++) {
x1[i] += x2[i];
}
}
};
int main() {
MyClass myInstance;
// Fill the arrays...
myInstance.add(myInstance.arr1, myInstance.arr2, myInstance.len);
}
add
peut déjà accéder à toutes les variables dont il a besoin, car il s'agit d'une méthode de classe, est-ce donc une mauvaise idée? Y a-t-il des raisons pour lesquelles je devrais ou ne devrais pas faire cela?
object-oriented
c++
class-design
methods
encapsulation
homme de papier
la source
la source
add
méthode sans argument qui opère directement sur ses internes? Juste pourquoi?add
méthode qui prend des arguments mais n'existe pas dans le cadre d'une classe. Juste une fonction pure pour ajouter deux tableaux ensemble.Réponses:
Il y a peut-être des choses avec la classe que je ferais différemment, mais pour répondre à la question directe, ma réponse serait
oui, c'est une mauvaise idée
Ma principale raison est que vous n'avez aucun contrôle sur ce qui est transmis à la
add
fonction. Bien sûr, vous espérez qu'il s'agit de l'un des tableaux membres, mais que se passe-t-il si quelqu'un passe dans un tableau différent qui a une taille inférieure à 100, ou si vous passez dans une longueur supérieure à 100?Ce qui se passe, c'est que vous avez créé la possibilité d'un dépassement de tampon. Et c'est une mauvaise chose tout autour.
Pour répondre à d'autres questions (pour moi) évidentes:
Vous mélangez des tableaux de style C avec C ++. Je ne suis pas un gourou du C ++, mais je sais que le C ++ a de meilleures façons (plus sûres) de gérer les tableaux
Si la classe a déjà les variables membres, pourquoi avez-vous besoin de les transmettre? C'est plus une question architecturale.
D'autres personnes ayant plus d'expérience en C ++ (j'ai cessé de l'utiliser il y a 10 ou 15 ans) peuvent avoir des façons plus éloquentes d'expliquer les problèmes et trouveront probablement plus de problèmes également.
la source
vector<int>
serait plus approprié; la longueur serait alors inutile. Alternativementconst int len
, puisque le tableau de longueur variable ne fait pas partie de la norme C ++ (bien que certains compilateurs le prennent en charge, car c'est une fonctionnalité facultative en C).std::array
qui ne se désintègre pas en le passant aux paramètres, a un moyen plus pratique d'obtenir sa taille, est copiable et a accès avec une vérification des limites facultatives, sans avoir de surcharge Tableaux de style C.L'appel d'une méthode de classe avec certaines variables de classe n'est pas nécessairement mauvais. Mais le faire de l'extérieur de la classe est une très mauvaise idée et suggère une faille fondamentale dans votre conception OO, à savoir l'absence d' encapsulation appropriée :
len
la longueur du tableau et l'utiliser de manière cohérente. Cela va à l'encontre du principe du moindre savoir . Une telle dépendance à l'égard des détails internes de la classe est extrêmement sujette aux erreurs et risquée.len
rendre plus modernesstd::vector<int>
), car cela vous obligerait à changer également tout le code en utilisant votre classe.MyClass
objets en corrompant certaines variables publiques sans respecter les règles (appelées invariants de classe )Vous devez refactoriser votre code et:
private
ouprotected
, à moins qu'il n'y ait une bonne raison de ne pas le faire.object.action(additional parameters for the action)
.la source
Lorsque l'intention de cette conception est que vous souhaitez pouvoir réutiliser cette méthode pour des données qui ne proviennent pas de cette instance de classe, vous pouvez alors la déclarer en tant que
static
méthode .Une méthode statique n'appartient à aucune instance particulière d'une classe. C'est plutôt une méthode de la classe elle-même. Étant donné que les méthodes statiques ne sont pas exécutées dans le contexte d'une instance particulière de la classe, elles ne peuvent accéder qu'aux variables membres qui sont également déclarées comme statiques. Étant donné que votre méthode
add
ne fait référence à aucune des variables membres déclarées dansMyClass
, elle est un bon candidat pour être déclarée comme statique.Cependant, les problèmes de sécurité mentionnés par les autres réponses sont valides: vous ne vérifiez pas si les deux baies sont au moins
len
longues. Si vous souhaitez écrire du C ++ moderne et robuste, vous devez éviter d'utiliser des tableaux. Utilisezstd::vector
plutôt la classe autant que possible. Contrairement aux tableaux réguliers, les vecteurs connaissent leur propre taille. Vous n'avez donc pas besoin de suivre vous-même leur taille. La plupart (pas toutes!) De leurs méthodes font également une vérification automatique des liens, ce qui garantit que vous obtenez une exception lorsque vous lisez ou écrivez après la fin. L'accès régulier aux baies ne fait pas de vérification des limites, ce qui entraîne au mieux une erreur de segmentation et peut, au pire, entraîner une vulnérabilité de dépassement de tampon exploitable .la source
Une méthode dans une classe manipule idéalement des données encapsulées à l'intérieur de la classe. Dans votre exemple, il n'y a aucune raison pour que la méthode add ait des paramètres, utilisez simplement les propriétés de la classe.
la source
Passer (une partie de) un objet à une fonction membre est très bien. Lors de l' implémentation de vos fonctions, vous toujours devez être conscient de l' aliasing possible , et les conséquences de celle - ci.
Bien sûr, le contrat peut laisser certains types d'alias indéfinis même si la langue le prend en charge.
Exemples marquants:
L'auto-affectation de mouvement, d'autre part, bien qu'elle ne devrait pas exploser dans votre visage, n'a pas besoin d'être un non-op.
v.push_back(v[2]);
.std::copy()
suppose que la destination ne commence pas à l'intérieur de la source.Mais votre exemple a différents problèmes:
this
. Il agit comme une fonction utilitaire gratuite qui est simplement au mauvais endroit.En résumé: oui, cet exemple est mauvais. Mais pas parce que la fonction membre obtient des objets membres passés.
la source
Concrètement, cela est une mauvaise idée pour plusieurs bonnes raisons, mais je ne suis pas sûr que tous font partie intégrante de votre question:
vector<int>
vous faciliterait la vie.la source
Il s'agit d'une approche classique «C avec classes» du C ++. En réalité, ce n'est pas ce qu'un programmeur C ++ expérimenté écrirait. D'une part, l'utilisation de tableaux C bruts est à peu près universellement déconseillée, sauf si vous implémentez une bibliothèque de conteneurs.
Quelque chose comme ça serait plus approprié:
la source