0

I'm building a program just to increase my OOP skills. This is my project structure:

Project
 -.vscode
 -build
 -includes
   - ContactInfo.h
   - Customer.h
   - Owner.h
   - PersonalInfo.h
   - User.h
 -src
   - ContactInfo.cpp
   - Customer.cpp
   - Owner.cpp
   - PersonalInfo.cpp
   - User.cpp
   - wrapper.h
   - wrapper.cpp
   - main.cpp
 - CMakeLists.txt

The problem is when I type command make in cmd at build file path, I get this following error:

duplicate symbol '_key' in:
    CMakeFiles/make_test_project.dir/src/main.cpp.o
    CMakeFiles/make_test_project.dir/src/wrapper.cpp.o
duplicate symbol '_customers' in:
    CMakeFiles/make_test_project.dir/src/main.cpp.o
    CMakeFiles/make_test_project.dir/src/wrapper.cpp.o
ld: 2 duplicate symbols for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [make_test_project] Error 1
make[1]: *** [CMakeFiles/make_test_project.dir/all] Error 2
make: *** [all] Error 2

I can guess what's happening here, I'm basically including wrapper.h file in both main.cpp and wrapper.cpp files but I don't know how to fix it. I also want to keep my project structure this way. So is there any way to fix this error ?

This is my wrapper.h file:

#ifndef WRAPPER_H
#define WRAPPER_H

#include "../includes/Customer.h"

#include <vector>
#include <iostream>

char key;

void printUI();
void RunApplication();
PersonalInfo CreatePersonalInfo(std::string &, std::string &, int & );
ContactInfo CreateContactInfo(std::string &, std::string &, std::string &, int&);
void DisplayAllCustomers();
void AddCustomerToList(Customer &);
Customer CreateCustomer(PersonalInfo &, ContactInfo &);

std::vector<Customer> customers;

#endif

This is my main.cpp file:

#include "wrapper.h"

int main()
{   
    RunApplication();
}


This below is my CMakeLists.txt file:

cmake_minimum_required(VERSION 3.13)

project(cmake_test_project)

set(CMAKE_CXX_STANDARD 17)

add_executable(make_test_project src/main.cpp src/wrapper.cpp src/ContactInfo.cpp src/PersonalInfo.cpp src/Customer.cpp src/User.cpp)

Note: I'm not gonna share wrapper.cpp file since it's a file composed of almost 120 lines but I can give you the information that I also included wrapper.h file in wrapper.cpp file.

Please feel free to ask more information, Thanks.

Ali Ziya ÇEVİK
  • 186
  • 1
  • 1
  • 8
  • 2
    See [c++ global object](https://stackoverflow.com/questions/4918010/c-global-object) to solve at least one issue, but the error also mentions undefined reference, which means linker cannot see the definition of `printUI` in any source file. – Yksisarvinen May 13 '21 at 11:43
  • That was the previous error I'd been dealing. I didn't mean to ask that error, I copied the wrong error. I put the correct one now though. – Ali Ziya ÇEVİK May 13 '21 at 11:47
  • 1
    change to `extern char key;` and add a `char key;` to One .cpp file. – Surt May 13 '21 at 11:49
  • 1
    @Ali Then see the linked question. You may not put definition of global variable in header file, except when it would be `inline` (doable since C++17). You should move those variables to a .cpp file and only `extern` them in header to make them accessible in other .cpp files. – Yksisarvinen May 13 '21 at 11:51
  • @Surt Thanks, that fixed the problem with the key. Now there is only one duplicate left. Can you check that too ? – Ali Ziya ÇEVİK May 13 '21 at 11:51
  • 1
    Do the same for `customers`. – Yksisarvinen May 13 '21 at 11:52
  • @Yksisarvinen by the way, should I seperate ```extern``` ```.h```files and normal ```.h files ``` into 2 separate ```.h```files ? – Ali Ziya ÇEVİK May 13 '21 at 11:57
  • 1
    The first thing would be to not use global objects. If you do need them, it's just a matter of your convention where to place the externs. – Yksisarvinen May 13 '21 at 12:02

1 Answers1

1

In your wrapper.h

extern char key;

void printUI();
void RunApplication();
PersonalInfo CreatePersonalInfo(std::string &, std::string &, int & );
ContactInfo CreateContactInfo(std::string &, std::string &, std::string &, int&);
void DisplayAllCustomers();
void AddCustomerToList(Customer &);
Customer CreateCustomer(PersonalInfo &, ContactInfo &);

extern std::vector<Customer> customers;

And declare both in One and only one .cpp file.

If you got C++17 you can just exchange the extern with inline and your done.

Surt
  • 15,501
  • 3
  • 23
  • 39