1

I keep getting this linker error below

enter image description here

and it seems to be caused by the constructor below

/*Card.h*/
#ifndef Card_H
#define Card_H

#pragma once
#include <iostream>
using namespace std;
#include <cassert> //for assert()
#include <string>
#include <time.h>

using namespace std;

/*Card.h*/
enum color { club, diamond, heart, spade };

class Card {
public:
    Card(color c = club, int v = 1);//this line

private:
    color col;
    int val;
};

/*Constructor*/
Card::Card(color c, int v) {// and this too
    col = c;
    val = v;
}

#endif

I am confused as to how neither of the player or myFile could have redefined card given they dont even include the Card.h file.

Icarus
  • 501
  • 2
  • 16
  • [Please do not upload images of code/errors when asking a question.](//meta.stackoverflow.com/q/285551) – Ken White Nov 06 '20 at 01:47
  • Anything in a header shows up in every file including the header. That's fine for declarations, but definitions... Not so good. Every file that includes Card.h now has its own copy of `Card::Card` and the linker doesn't even bother sorting out which one is the correct one to use or care if they are all identical. It just spits out an error and exits. – user4581301 Nov 06 '20 at 01:52

2 Answers2

2

In your header file:

Card::Card(color c, int v) {

This is a definion of Card's constructor. This means that every translation unit (a C++ source file), that #includes this header ends up defining this constructor. Remember that an #include of a header file is exactly equivalent to logically inserting the contents of the header file, verbatim, into the C++ source file that #includes it.

If you have ten C++ source files that include this header this means that each one of the ten C++ source file defines this constructor.

This violates C++'s One Definition Rule, which requires that each (non-inlined) object or function gets defined exactly once. No more, no less.

This explains your compilation error. You simply need to move this constructor's definitions to exactly one of your C++ source files.

Sam Varshavchik
  • 114,536
  • 5
  • 94
  • 148
  • Thank you that makes a lot of sense. I guess the prof just didnt bother to check her own code. I will accept once it allows me to. – Icarus Nov 06 '20 at 01:59
1

The implementation of the constructor should go in a file named Card.cpp

Card.h

#ifndef Card_H
#define Card_H

#include <iostream>
#include <cassert>
#include <string>
#include <time.h>

using namespace std;

enum color { club, diamond, heart, spade };

class Card {
public:
    Card(color c = club, int v = 1);

private:
    color col;
    int val;
};

#endif

Card.cpp

#include "Card.h"

Card::Card(color c, int v) {
    col = c;
    val = v;
}
Bill Lynch
  • 80,138
  • 16
  • 128
  • 173
  • hi unfortunately the header file is given as part of an assignment and we are not allowed to change it – Icarus Nov 06 '20 at 01:51
  • 1
    Well then point your instructor at this stackoverflow question and implement all of the rest of your code in a single cpp file. – Bill Lynch Nov 06 '20 at 01:51
  • @Icarus also get your hands on some extra reference materials for self defense and education. Your instructor might not be well qualified for teaching C++. Don't be too surprised. It happens far more often than anyone likes to see. – user4581301 Nov 06 '20 at 01:54
  • I don't think there's any reason to overreact/freak out/recommend the OP burns their school down; they probably just misinterpreted the material. There are comments in there that almost suggest that some of it should be treated as a header and some not, but they're just not well written. So lines of text intended to be copied into two files, instead ended up copied into one. All it needs is a clarification in the lecture notes. The instructor can surely explain this in 20 seconds flat with no need for any drama. ‍♂️ – Asteroids With Wings Nov 06 '20 at 02:31