2010-03-19 5 views
2

J'ai récemment refacturé le code comme ceci (MyClass à MyClassR).Fonction surchargée appelée avec un paramètre, mais je pensais que j'avais passé deux

#include <iostream> 

class SomeMember 
{ 
public: 
    double m_value; 

    SomeMember() : m_value(0) {} 
    SomeMember(int a) : m_value(a) {} 
    SomeMember(int a, int b) 
    : m_value(static_cast<double>(a)/3.14159 + 
      static_cast<double>(b)/2.71828) 
    {} 
}; 


class MyClass 
{ 
public: 
SomeMember m_first, m_second, m_third; 

MyClass(const bool isUp, const int x, const int y) 
{ 
    if (isUp) 
    { 
    m_first = SomeMember(x); 
    m_second = SomeMember(y); 
    m_third = SomeMember(x, y); 
    } 
    else 
    { 
    m_first = SomeMember(y); 
    m_second = SomeMember(x); 
    m_third = SomeMember(y, x); 
    } 
} 
}; 


class MyClassR 
{ 
public: 
SomeMember m_first, m_second, m_third; 

MyClassR(const bool isUp, const int x, const int y) 
: m_first(isUp ? x : y) 
, m_second(isUp ? y : x) 
, m_third(isUp ? x, y : y, x) 
{ 
} 
}; 


int main() 
{ 
    MyClass a(true, 1, 2); 
    MyClassR b(true, 1, 2); 

    using namespace std; 
    cout.precision(10); 
    cout 
     << "a:" << endl 
     << "\tfirst: " << a.m_first.m_value 
     << "\tsecond: " << a.m_second.m_value 
     << "\tthird: " << a.m_third.m_value << endl; 

    cout 
     << "b:" << endl 
     << "\tfirst: " << b.m_first.m_value 
     << "\tsecond: " << b.m_second.m_value 
     << "\tthird: " << b.m_third.m_value << endl; 

    return 0; 
} 
  • Quelle est l'erreur,
  • pourquoi est-il compilent (testé avec VC6 ainsi que VC9 niveau 4 d'avertissement: aucune plainte) et
  • quelle est la bonne façon de le faire ?

Je suppose que j'ai déjà toutes ces réponses mais je pense que c'est un problème intéressant à partager.

Mise à jour
code Extended il est donc "copier coller & & execute" able. VC9 ne m'a donné aucune plainte non plus alors VC6 n'est pas le problème ici.
Pour être complet, la sortie est:

a: 
     first: 1  second: 2  third: 1.054069532 
b: 
     first: 1  second: 2  third: 1.004499999 
+0

Je ne vois aucune raison pour une erreur. C'est absolument parfait et compile, exécute comme prévu – mukeshkumar

+0

Question artificielle, rhétorique. Suggère de le fermer. – Suma

+0

@Suma Le code est artificiel puisqu'il est simplifié. Le problème s'est vraiment produit ... – foraidt

Répondre

8

Je ne sais pas ce que vous attendez exactement mais commençons ...

  • Tout d'abord, VC6 fossé. Sérieusement. L'utiliser est un énorme problème car il n'est tout simplement pas conforme aux normes et exclut beaucoup d'options. L'utiliser correctement, c'est comme jouer à la roulette russe. Le constructeur de m_third ne fait pas ce que vous pensez qu'il fait. Vous ne pouvez pas écrire une expression conditionnelle comme ceci: "plusieurs paramètres" n'est pas une expression valide en C++, et l'opérateur conditionnel fonctionne sur les expressions.

  • Le code compile car il est toujours correct, il ne fait tout simplement pas ce que vous voulez. Au lieu d'utiliser « plusieurs paramètres », il évalue l'opérateur de point de séquence (,) qui prend juste la dernière valeur de l'expression, de sorte que votre condition est effectivement équivalent à: isUp ? y : x

  • La bonne manière est d'utiliser deux: conditionals m_third(isUp ? x : y, isUp ? y : x)

  • le troisième constructeur de SomeMember est erroné, la valeur peut entraîner un dépassement, ce qui donne une valeur négative - je doute fortement que c'est ce que vous voulez.

+0

(1) VC6 n'est pas mon choix, malheureusement .. (2) La classe SomeMember est juste là pour fournir du code qui compile. J'ai pensé au problème de débordement et ai fait m_value un long au lieu de et int donc j'ai supposé, tout 2 ints entrerait dedans, n'est-ce pas? – foraidt

+7

S'il vous plaît prendre d'assaut dans la pièce où la personne vous obligeant à utiliser VC6 réside, et jeter une chaise à eux. Pour moi. Vous pouvez éventuellement ajouter des chaises supplémentaires pour d'autres membres de l'OS. Je recommande de veiller à ce que les jambes de la chaise soient dirigées vers la tête pour une douleur maximale. – GManNickG

+1

Quelqu'un pourrait-il jeter des parenthèses ou quelque chose autour des choses pour clarifier ce qui se passe où? J'ai cru comprendre ce que le code faisait, et en lisant cette réponse, je pense encore que je comprends ce que fait le code, et pourtant je me trompe apparemment. –

2
m_third(isUp ? x, y : y, x) 

Cela semble mal être. Le premier x est une expression inutile car il n'a pas d'effets secondaires et le résultat n'est pas utilisé, puis les deux côtés du : ont la même valeur et les effets secondaires, donc ?: peut être éliminé comme l'expression avant le ? n'a également aucun effet secondaire .

m_third(y, x) 

Mais maintenant, il ne fait pas ce que fait le code original ... est-ce l'erreur?

+0

Dans un commentaire à une réponse supprimée, vous indiquez qu'une «expression-virgule n'est pas une sous-expression finale valide d'une expression constionnelle». Pourquoi ne le serait-il pas? –

+0

@dribeas: C'est les règles de grammaire! Le dernier bit d'une expression conditionnelle doit être une expression d'affectation, ce qui est plus restrictif que l'expression _expression_. Cela signifie que la virgule après la seconde manière met fin à l'expression conditionnelle et doit être interprétée comme faisant partie d'autre chose. Dans ce cas, _expression-list_ est l'initialiseur du membre. Vous pourriez mettre des parenthèses autour de l'expression virgule pour la transformer en une expression primaire et ce serait une partie finale valide d'une expression conditionnelle. –

+0

Oui, c'est l'erreur. Le code d'origine ('MyClass') appelé' SomeMember (x, y) 'ou' SomeMember (y, x) 'en fonction de l'indicateur' isUp'. Le code refactorisé ('MyClassR') était destiné à faire la même chose mais ce n'est pas le cas. – foraidt

0

Quelle est l'erreur Quelle est la bonne façon de le faire?

Je suppose que votre intention est de montrer une sorte d'utilisation naïve de l'opérateur virgule en combinaison avec ternaire?, Peut-être il y a une certaine priorité de l'opérateur intelligent et inattendu Gotcha caché, mais que je pense que le code est tout à fait artificielle. Si tel est le cas, je dirais que la "bonne façon de le faire" est de ne pas utiliser C++ ou d'abord l'apprendre avant de l'utiliser. Oui, il a beaucoup de constructions qui peuvent ressembler à des "bizarreries" et vous pouvez créer beaucoup de code à la recherche étrange accepté par un compilateur. En utilisant C++, je dirais que vous êtes supposé connaître les outils.

Pourquoi ne compile

Parce qu'il ne contient aucune erreur et il est un code C++ correct sans ambiguïtés.