Corrija las múltiples definiciones de un error de función en C++

Muhammad Husnain 12 octubre 2023
Corrija las múltiples definiciones de un error de función en C++

Este artículo trata sobre la solución al error frecuente en C++, que es múltiples definiciones de una función.

Soluciona el error múltiples definiciones de una función en C++

Este error generalmente se produce cuando intentamos separar el prototipo de función y su definición. Por lo tanto, se recomienda que separe los prototipos y las definiciones en diferentes archivos e incluya el archivo correspondiente.

Considere el siguiente ejemplo para entender el problema.

Código de ejemplo (file1.cpp):

// file1.cpp
#include <iostream>
using namespace std;

class classB {
  friend void f1();

 public:
  classB(int i = 1, int j = 2) : a(i), b(j) {
    cout << "Hello from constructor\n";
  }

 private:
  int a;
  int b;
  void printfun() { cout << "a=" << a << endl << "b=" << b << endl; }
};
void f1() {  // ERROR HERE
  cout << "f1 start" << endl;
  classB tmp(3, 5);
  tmp.printfun();
  cout << "f1 end" << endl;
}

Código de ejemplo (main.cpp):

// main.cpp
#include <iostream>

#include "file1.cpp"
using namespace std;

int main() {
  cout << "calling function" << endl;
  f1();
  cout << "exit from main" << endl;
  return 0;
}

Esto es lo que está sucediendo en su circunstancia. Debido a #include en el archivo file1.cpp, tanto file1.cpp como main.cpp incluyen una definición de f1(), y el enlazador no sabe cuál usar en su programa y se queja de ello.

La solución es eliminar el archivo CPP que contiene la definición de f1() de main.cpp y, en su lugar, incluir la declaración de f1() en un archivo de encabezado separado e incluirlo en main.cpp. El compilador tendrá que lidiar con la declaración de f1(), y el enlazador tendrá solo una definición de f1() de file1.cpp para confiar.

Código de ejemplo (file1.h):

// file1.h
#include <iostream>

class classB {
  friend void f1();

 public:
  classB(int i = 1, int j = 2) : a(i), b(j) {
    std::cout << "Hello from constructor\n";
  }

 private:
  int a;
  int b;
  void printfun() { std::cout << "a=" << a << endl << "b=" << b << std::endl; }
};

Código de ejemplo (file1.cpp):

// file1.cpp
#include "file1.h"
using namespace std;
void f1() {
  cout << "f1 start" << endl;
  classB tmp(5, 6);
  tmp.printfun();
  cout << "f1 end" << endl;
}

Código de ejemplo (main.cpp):

// main.cpp
#include <iostream>

#include "file1.h"
using namespace std;

int main() {
  cout << "calling function" << endl;
  f1();
  cout << "exit from main" << endl;
  return 0;
}

Comencemos con el archivo de cabecera file1.h. Los archivos de encabezado contienen las definiciones de todo, como definiciones de funciones, cualquier definición de estructura o clase, o cualquier definición de constantes.

Esta extensión .h le dice al compilador que este archivo no debe compilarse. Es como un archivo de texto y cualquier persona puede leerlo.

Esto implica que el archivo de encabezado es un archivo de documentación. Si algún programador quiere usar algunas funciones en el futuro, solo necesita verificar el prototipo de las funciones y no necesita entrar en detalles sobre las definiciones de funciones.

Por último, el código de la plantilla también debe estar en el archivo de encabezado.

El archivo CPP ahora define la función declarada en el archivo de encabezado. Esto le dice al compilador que este archivo debe compilarse y convertirse en un archivo binario.

La integridad de su código estará protegida y nadie más podrá modificarlo sin su permiso. Esto significa que esta separación de código también garantiza la seguridad de sus archivos de código.

Una razón más detrás de esta técnica es la portabilidad. Por ejemplo, ha escrito un código de búsqueda binaria que se puede usar más tarde en muchos otros programas.

Si tiene estos archivos separados para funciones, puede usarlas fácilmente en cualquier otro proyecto.

Por fin, el archivo principal contiene solo la función principal e incluye el archivo de encabezado en la parte superior. Este archivo contiene solo la función principal, que solo llama a todas las funciones y nada más.

Muhammad Husnain avatar Muhammad Husnain avatar

Husnain is a professional Software Engineer and a researcher who loves to learn, build, write, and teach. Having worked various jobs in the IT industry, he especially enjoys finding ways to express complex ideas in simple ways through his content. In his free time, Husnain unwinds by thinking about tech fiction to solve problems around him.

LinkedIn

Artículo relacionado - C++ Error