Effective C l'article 46: (S'il vous plaît définir la fonction de membre non modèle en cas de besoin conversion de type) du modèle et la programmation générique

Un exemple d'erreur de modèle de fonction non-membre

  • Nous avons dit en termes de 24, pour la classe rationnelle, afin de faire toutes les opérations de multiplication sont accessibles par l'opération, en tant que version de fonction non-membre , nous serons en fonction de l' opérateur * () est défini (les détails peuvent revenir pour voir). Mais pour le modèle, ces règles ne peuvent pas tenir

  • Par exemple nous allons mettre la fonction * rationnelle et l' opérateur () est défini comme un modèle de code est suit comme:
//下面与条款24都相同,只是改为了模板
template<typename T>
class Rational {
public:
    Rational(const T& numerator = 0, const T& denominator = 1);
    const T numerator()const;
    const T denominator()const;
};

template<typename T>
const Rational<T> operator*(const Rational<T>& lhs, const Rational<T>& rhs)
{	
}
  • Maintenant , nous écrivons le code suivant ne peut pas compiler. Par exemple:
Rational<int> oneHalf(1, 2);

//在条款24中,Rational和operator*为非模板,此处代码可编译通过
//此处,Rational和operator*为模板,编译不通过
Rational<int> result = oneHalf * 2;

Analyse d'erreur

  • La raison de cette erreur est: au- dessusfonction « OneHalf * 2 » Aucun opérateur de correspondance * (),entraîne une erreur
  • raison:
    • OneHalf de type de Rational <int>, il correspond au modèle de fonction * opérateur (), et le modèle de fonction * opérateur () instance de modèle type T en int
    • Cependant, lorsque le second paramètre de fonctionnement, lorsque deux int, la fonction opérateur * () est un modèle ne peut pas être déduite à partir d'un type int T
    • Ainsi, le compilateur finale ne peut pas trouver une fonction * opérateur approprié () et conduire à des erreurs
  • Dans l'opérateur non-modèle * () à, opérateur * () 2 peut être une conversion implicite (conversion implicite rationnelle fournit les détails, puis passer àarticle 24) commeobjets Rational. Mais dans le modèle, la conversion implicite n'est pas autorisé
  • prises pour tirer l'argument du modèle facteur décisif

D'autre part, la fonction de modèle déclaré comme ami

  • Dans la « une », la classe de modèle et fonctions de modèle que nous utilisons le mauvais, une solution est à l'opérateur () * déclarée en tant que classes d'ami de modèle Rational (ami)
  • Let a été de modifier deux fois, et, finalement, le mauvais code

La première modification (compilateur, mais mauvais lien)

  • Nous avons d' abord l' opérateur () * Déclaré comme ami rationnelle . Code est la suivante:
template<typename T>
class Rational {
public:
    //友元,函数声明
    friend const Rational operator*(const Rational& lhs, const Rational& rhs);
};

//函数定义
template<typename T>
const Rational<T> operator*(const Rational<T>& lhs, const Rational<T>& rhs);


int main()
{
    Rational<int> oneHalf(1, 2);
    //编译通过,但是链接时出错
    Rational<int> result = oneHalf * 2;

    return 0;
}
  • Note: Le plus haut ami dansvie, nous n'ajoutons pas dans le dos rationnel <T>, qui rationnel <T> est le même,deux sont
  • Compilé en raison de:
    • OneHalf lorsque l'objet est défini, le programme va générer un rationnel <int> classe définie, puis la classe rationnelle <int> est instancié sur
    • classe rationnelle <int> Après avoir été instancié, la fonction opérateur ami * () sont automatiquement déclarés hors (Note: ne déclarée mais non définie)
    • Une fois la fonction opérateur ami * () est déclaré hors, la fonction est une fonction, plutôt que d'un modèle, afin que nous puissions transmettre à la fonction 2 (2 implicitement et la conversion de type de paramètre, sera converti en 2 rationnelle)
    • Ainsi, le code ci-dessus sur elle par le compilateur, mais des erreurs lien (ci-dessous)
  • La raison du lien d'erreur:
    • Parce que la déclaration classe rationnelle <int> est instancié est sorti, ami vient de l'opérateur * (), mais ne se définit pas, donc l'erreur de programme

Le deuxième amendement (version correcte)

  • La compilation de code ci-dessus, mais le lien à travers, étant donné que la définition n'a pas pu trouver l'opérateur * () de
  • méthode d'erreur Lien à résoudre est: En même temps, la définition de cette fonction dans une fonction ami déclaration. Code est la suivante:
template<typename T>
class Rational {
public:
    //声明的时候,同时实现该函数(备注,该函数虽然在类中定义,但不属于成员函数)
    friend const Rational operator*(const Rational& lhs, const Rational& rhs)
    {
        return Rational(lhs.numerator()*rhs.numerator(),
        lhs.denominator()*lhs.denominator());
    }
};
  • Un autre avantage de l'ami ici: Bien que cette fonction nous déclarons ami, mais n'a pas eu accès à une catégorie de membres non publiques, de façon relativement sûre

Troisièmement, faire des appels de fonctions d'aide d'ami (lié à la ligne)

  • Nous avons dit que , en termes de 30, si la fonction est définie dans la classe deviendra en ligne, et donc ce qui précède , nous définir opérateur ami dans la classe de () * sera appelée ligne
  • Afin de minimiser l'impact de la ligne apporte, nous pouvons:
    • Nous ne pouvons pas faire () * dans quel opérateur, sera la chose complète à une autre fonction auxiliaire
    • L'aide devrait être un modèle
  • Code est la suivante:

    • Pouropérateur de faire * () optimiséligne dans la classe, on définit une fonction d'assistance, dans laquelle l'opérateur complet * () est censé remplir la fonction

    • doMultiply () ne prend pas en charge le fonctionnement hybride (comme un objet et un int multiplication Rational), mais la fonction * () est appelée uniquement par l'opérateur, et l'opérateur * () supporte l'opération de mélange, et donc fonctionnel

//声明
template<typename T> class Rational

//函数声明(定义在下)
template<typename T>
const Rational<T> doMultiply(const Rational<T>& lhs, const Rational<T>& rhs);

template<typename T>
class Rational {
public:
    friend
        const Rational operator*(const Rational& lhs, const Rational& rhs)
    {
        //在其中调用doMultiply(),可使inline最优化
        return doMultiply(lhs, rhs);
    }
};

//完成原本operator*()要完成的功能
template<typename T>
const Rational<T> doMultiply(const Rational<T>& lhs, const Rational<T>& rhs)
{
    return Rational<T>(lhs.numerator()*rhs.numerator(),
        lhs.denominator()*lhs.denominator());
}

IV Résumé

  • Lorsque nous écrivons un modèle de classe, et il fournit le « modèle associé à ce » soutien « de la fonction de tous les paramètres de la conversion de type implicite », définissez les fonctions définies comme « à l'intérieur du modèle de classe fonction ami »
Publié 1525 articles originaux · louange won 1084 · Vues 450000 +

Je suppose que tu aimes

Origine blog.csdn.net/qq_41453285/article/details/104887321
conseillé
Classement