0

Im creating a small program in which i have my files modularized, and i want to pass an array to a function in another file, but i cant get to pass it, since when i compile all my files it prompts me with:

undefined reference to `informesMain(Repartidor*, int)'

undefined reference to `repartidoresMain(Repartidor*, int)'

This is my main function, where i want to pass the array Repartidor repartidores[1120] down the program:

#include <iostream>
#include <stdlib.h>
#include "./shared/utils/file-utils.h"
#include "./shared/model/repartidor.model.h"
#include "./entities/repartidores/repartidores-controller.h"
#include "./modules/reports-controller.h"
using namespace std;

void printMainMenu(bool error);

int main() {
  unsigned userInput = 0;
  bool error = false;

  Repartidor repartidores[1120];
  int cantidadRepartidoresActuales = 0;

  do {
    printMainMenu(error);
    cin >> userInput; // TODO: Si el user mete un string, se rompe, handlear este caso y poner el error = true
    switch (userInput) {
      case 1:
        error = false;
        repartidoresMain(repartidores, cantidadRepartidoresActuales);
        break;
      case 2:
        error = false;
        informesMain(repartidores, cantidadRepartidoresActuales);
        break;
      case 0:
        break;
      default:
        error = true;
    }
  } while(userInput != 0);

  return 0;
}

void printMainMenu(bool error) {
  system("cls");
  if (error) cout<<"Opcion incorrecta!"<<endl<<endl;
  cout<<"1 - Gestionar Repartidores"<<endl;
  cout<<"2 - Informes"<<endl;
  cout<<"0 - Salir"<<endl<<endl;
}

Then i got the respective header files for the used functions above:

#pragma once
#include "../../shared/model/repartidor.model.h"

void repartidoresMain(Repartidor[], int);
#pragma once
#include "../shared/model/repartidor.model.h"

void informesMain(Repartidor[], int);

And here's the implementation for those functions, respectively:

#include <iostream>
#include <stdlib.h>
#include "repartidores-controller.h"
#include "../../shared/model/repartidor.model.h"
using namespace std;

void printRepartidoresMenu(bool error);

void repartidoresMain(Repartidor repartidores, int cantidadRepartidoresActuales) {
  unsigned userInput = 0;
  bool error = false;

  do {
    printRepartidoresMenu(error);
    cin >> userInput; // TODO: Si el user mete un string, se rompe, handlear este caso y poner el error = true
    switch (userInput) {
      case 1:
        error = false;
        // TODO: Funcion de alta definida en repartidores-actions.cpp
        break;
      case 0:
        error = false;
        return;
      default:
        error = true;
    }
  } while(userInput != 0);
}

void printRepartidoresMenu(bool error) {
  system("cls");
  if (error) cout<<"Opcion incorrecta!"<<endl<<endl;
  cout<<"1 - Alta repartidor"<<endl;
  cout<<"0 - Volver"<<endl<<endl;
}
#include "../shared/model/repartidor.model.h"
#include "./reports-controller.h"
#include <iostream>
#include <stdlib.h>
using namespace std;

void printInformesMenu(bool);

void informesMain(Repartidor repartidores, int cantidadRepartidoresActuales)
{
    unsigned userInput = 0;
    bool error = false;
    do {
        printInformesMenu(error);
        cin >> userInput; // TODO: Si el user mete un string, se rompe, handlear este caso y poner el error = true
        switch (userInput) {
        case 1:
            error = false;
            //TODO: Generar informe caso 1
            break;
        case 2:
            error = false;
            // TODO: Generar informe caso 2
            break;
        case 3:
            error = false;
            // TODO: Generar informe caso 3
            break;
        case 0:
            return;
        default:
            error = true;
        }
        
    } while(userInput != 0);
}


  void printInformesMenu(bool error)
  {
  system("cls");
  if (error) cout<<"Opcion incorrecta!"<<endl<<endl;
  cout<<"1 - Informar cantidad de repartidores por medio de transporte por zona"<<endl;
  cout<<"2 - Informar medios de transportes no existentes (de todas las zonas)"<<endl;
  cout<<"3 - Informar zonas con mas repartidores inscriptos"<<endl;
  cout<<"0 - Volver"<<endl<<endl;
  }

I want to mutate the array down the line, like when i just used a file, and passed an array as an argument, and i could mutate it as it was passed by reference by default, but i guess the problem is how im declaring that im passing the array in the .h files. Also i've seen people say "Declare a global variable in the .h file and use it" but i cant do that, if that would fix the issue.

I tried the following ways, with no success whatsover (in both declaration files)

void informesMain(Repartidor[], int);

void informesMain(Repartidor*, int);

void informesMain(Repartidor[1120], int);

void informesMain(Repartidor* [1120], int);

user4581301
  • 33,082
  • 7
  • 33
  • 54
Ramita
  • 21
  • 3
  • Are you permitted to use a vector? – drescherjm Jul 25 '23 at 01:30
  • 4
    ***Also i've seen people say "Declare a global variable in the .h file and use it"*** This is bad advice. Avoid using global variables. – drescherjm Jul 25 '23 at 01:31
  • 2
    Change `void informesMain(Repartidor repartidores, int cantidadRepartidoresActuales)` -> `void informesMain(Repartidor repartidores[], int cantidadRepartidoresActuales)` to match the prototype of `void informesMain(Repartidor[], int);`. Likely the others are a similar problem. – user4581301 Jul 25 '23 at 01:31
  • Also make absolutely certain that the files containing the definitions are being compiled and linked. Quite often a bug is really hard to solve because you have TWO bugs. – user4581301 Jul 25 '23 at 01:35
  • 2
    The error is about the *definition* being missing, not the *declaration*. So the problem is that you're not including the definition (the implementation file) when linking the program. – Chris Dodd Jul 25 '23 at 01:39
  • 2
    @user4581301 Thank you so much!! I couldnt find the bug, now it did compile. – Ramita Jul 25 '23 at 01:49
  • In other words, the problem was a *LINK* error. Glad you got it resolved! – paulsm4 Jul 25 '23 at 02:01
  • 1
    Why are you still using "C" style arrays? When you use std::array or std::vector you at least will not have bugs because of having to pass the array and its size as seperate arguments. include ` should not be necessary as this is a legacy "C" header file. It looks like your source of C++ training material is not really up-to-date. – Pepijn Kramer Jul 25 '23 at 03:11
  • Also includes with `..` in its paths are better solved by adding extra include paths to your compiler settings. – Pepijn Kramer Jul 25 '23 at 03:12
  • Your header declares `void informesMain(Repartidor[], int);` which is equivalent to `void informesMain(Repartidor *, int);`. The implementation of that function starts with `void informesMain(Repartidor repartidores, int cantidadRepartidoresActuales)` which doesn't match, so defines a function that was not declared in the header. One of the two needs to change, so they match. – Peter Jul 25 '23 at 06:23

1 Answers1

-2

In C++, when you pass an array to a function, you are actually passing a pointer to the first element of the array. Therefore, in your function declarations and definitions, you should be using a pointer to the type of the array elements. That is, for an array of Repartidor objects, you should be using Repartidor*.

However, in your function definitions, you forgot to indicate that the Repartidor parameter is an array. That's why you are getting undefined reference errors. The compiler is looking for a function that takes a single Repartidor object and an integer, but it only finds a function that takes a pointer to Repartidor and an integer.

Change the function definitions of repartidoresMain and informesMain to this:

void repartidoresMain(Repartidor* repartidores, int 
    cantidadRepartidoresActuales) {
  // Function body
}

void informesMain(Repartidor* repartidores, int 
    cantidadRepartidoresActuales) {
  // Function body
}

And leave the declarations in the header files as they were:

void repartidoresMain(Repartidor[], int);
void informesMain(Repartidor[], int);

Also ensure that you have included the .cpp files for repartidoresMain and informesMain in your compilation. Undefined reference usually means that the linker is unable to find the implementation of the declared function. This error occurs at link time, not compile time.

As for mutating the array, since you are passing the array as a pointer, changes you make to the elements will indeed be reflected in the original array. You are essentially passing the array by reference. You can change the values of the array elements and these changes will be seen outside the function. The only thing you cannot do is change the address that the pointer points to.

Hope it helps. Greetings from Paraguay.

ozzbetto
  • 47
  • 6
  • 1
    *you should be using Repartidor** not entirely true. `Repartidor[]` is 100% valid. – user4581301 Jul 25 '23 at 01:42
  • 1
    *The compiler is looking for a function that takes a single Repartidor object and an integer, but it only finds a function that takes a pointer to Repartidor and an integer.* the reverse, actually. The code example gets it right. – user4581301 Jul 25 '23 at 01:42
  • Yes you're correct, The important thing is that the function declarations in the header files match the function definitions. So, if the header file declares a function with a Repartidor[] parameter, the corresponding function definition must also use Repartidor[] (or equivalently, Repartidor*). Conversely, if the function is declared with a Repartidor* parameter, the function definition must also use Repartidor*. – ozzbetto Jul 25 '23 at 01:52
  • The *actual* problem was that the OP apparently didn't include his implementation (*.cpp) files in his link command. Once he did so ... "everything worked" :) – paulsm4 Jul 25 '23 at 02:03
  • @paulsm4 very likely there were two problems, but the mismatch between the declaration and definition was most definitely a problem in the given example. There are a few details to clean up in this answer, but it is mostly correct. – user4581301 Jul 25 '23 at 02:19
  • @user4581301 - Point well taken. The actual function signatures (e.g. `repartidoresMain(Repartidor repartidores, int cantidadRepartidoresActuales)`) did *NOT* match either the .h prototype, or the call from "main()". Which would also cause the link errors. But as you said: "Repartidor[] is 100% valid". Hopefully ozzbetto will (as you suggested) "clean up" his answer. – paulsm4 Jul 25 '23 at 03:20