Maison >développement back-end >C++ >Pourquoi l'inclusion d'un fichier d'en-tête avec une définition de fonction dans plusieurs fichiers sources entraîne-t-elle une erreur « définitions multiples » ?

Pourquoi l'inclusion d'un fichier d'en-tête avec une définition de fonction dans plusieurs fichiers sources entraîne-t-elle une erreur « définitions multiples » ?

Mary-Kate Olsen
Mary-Kate Olsenoriginal
2024-11-16 02:07:03553parcourir

Why does including a header file with a function definition in multiple source files lead to a

Erreur de définition multiple dans le fichier d'en-tête

Définition du problème

Considérez l'exemple de code suivant :

// complex.h
#include <iostream>

class Complex {
public:
   Complex(float Real, float Imaginary);

   float real() const { return m_Real; };

private:
   friend std::ostream& operator<<(std::ostream& o, const Complex& Cplx);

   float m_Real;
   float m_Imaginary;
};

std::ostream& operator<<(std::ostream& o, const Complex& Cplx) {
   return o << Cplx.m_Real << " i" << Cplx.m_Imaginary;
}

// complex.cpp
#include "complex.h"

Complex::Complex(float Real, float Imaginary) {
   m_Real = Real;
   m_Imaginary = Imaginary;
}

// main.cpp
#include "complex.h"
#include <iostream>

int main()
{
   Complex Foo(3.4, 4.5);
   std::cout << Foo << "\n";
   return 0;
}

Lors de la compilation de ceci code, le compilateur signale une erreur :

multiple definition of operator<<(std::ostream&, Complex const&)

Analyse des erreurs

La raison de cette erreur est que la définition de l'opérateur<< la fonction dans complex.h n'est pas une déclaration mais une définition réelle. Cela signifie que lorsque complex.cpp et main.cpp incluent le fichier d'en-tête, le compilateur tente de définir la fonction deux fois. Cela conduit à une erreur de définition multiple.

Le compilateur ne se plaint pas de la fonction membre publique real() car elle est implicitement intégrée. Cela signifie que le compilateur génère le code pour real() dans chaque unité de traduction qui l'utilise.

Solutions

Il existe deux solutions principales à ce problème :

  1. Faire de l'opérateur<< une fonction en ligne :

    En marquant l'opérateur<< fonctionne comme en ligne, il peut être défini dans plusieurs unités de traduction.

    inline std::ostream& operator<<(std::ostream& o, const Complex& Cplx) {
       return o << Cplx.m_Real << " i" << Cplx.m_Imaginary;
    }
  2. Opérateur de déplacement<< Définition de complex.cpp :

    Vous pouvez également définir l'opérateur<< fonction dans le fichier source complex.cpp, ce qui garantit qu'il n'est défini qu'une seule fois.

Solution supplémentaire

En plus d'utiliser le mot-clé en ligne ou de déplacer la définition vers une source fichier, il existe une autre solution possible :

  1. Utiliser des protections d'en-tête dans les définitions de fonctions :

    Vous pouvez ajouter des protections d'en-tête autour de la définition de fonction pour éviter qu'il soit défini plus d'une fois.

    #ifndef OPERATOR_LT_LT_DEFINED
    #define OPERATOR_LT_LT_DEFINED
    
    std::ostream& operator<<(std::ostream& o, const Complex& Cplx) {
       return o << Cplx.m_Real << " i" << Cplx.m_Imaginary;
    }
    
    #endif // OPERATOR_LT_LT_DEFINED

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn