Попытка одновременно скомпилировать три файла шаблона .cpp приводит к «ошибке: переопределение метода» - PullRequest
0 голосов
/ 25 октября 2019

У меня есть проект для университета, который мне удалось получить с помощью моей собственной команды makefile / Terminal. НО я получаю ноль баллов на университетском авто маркере. Я думаю, это потому, что они используют make-файл, который пытается выполнить все три файла cpp в одной строке с компилятором (если это вообще возможно), трудно сказать, потому что маркер не дает никакой обратной связи. Когда я пытаюсь скомпилировать все три файла .cpp (g ++ main.cpp A.cpp B.cpp), я получаю следующие сообщения об ошибках:

  • B.cpp: 4: 3: ошибка: переопределение'TB :: getVal ()' TB :: getVal () {
  • A.cpp: 4: 6: ошибка: переопределение 'void A :: print (B)' void A :: print (BbInstance) {

В моем MRE необходимо сохранить следующее:

  • A и B должны иметь файлы .h и .cpp
  • main.cpp может включать только «Ah»
  • A должен требовать B, чтобы он работал

Вот мое MRE: - Он создает экземпляр B, а затем использует экземпляр Aраспечатать сообщение со значением экземпляра B.

main.cpp

#include "A.h"

int main(){
  B<char> b1;
  b1.val='B';
  A<char> a1;
  a1.print(b1);
}

А *

#ifndef AAAA
#define AAAA

#include<iostream>
#include "B.h"

using namespace std;

template <class T>
class A{
public:
  void print(B<T> bInstance);
};

#include "A.cpp"

#endif

A.cpp

#include "A.h"

template <class T>
void A<T>::print(B<T> bInstance){
  cout<<"I am A, and I am using "<<bInstance.getVal()<<endl;
}

Bh

#ifndef BBBB
#define BBBB

template <class T>
class B{
public:
  T val;
  T getVal();
};

#include "B.cpp"

#endif

B.cpp

#include "B.h"

template <class T>
T B<T>::getVal(){
  return val;
}

Рабочие команды компиляции и запуска

g++ main.cpp

./a.out

Команды, с которыми он должен работать (если возможно)

g++ main.cpp A.cpp B.cpp

./a.out

Ответы [ 2 ]

0 голосов
/ 25 октября 2019

Ваша проблема с файлами в том виде, в каком они есть сейчас, заключается в том, что когда вы пытаетесь скомпилировать B.cpp, тогда это:

#include "B.h"

template <class T>
T B<T>::getVal(){
  return val;
}

и это:

#ifndef BBBB
#define BBBB

template <class T>
class B{
public:
  T val;
  T getVal();
};

#include "B.cpp"

#endif

объединяется в следующее:

#ifndef BBBB
#define BBBB

template <class T>
class B{
public:
  T val;
  T getVal();
};

#ifndef BBBB     // <- BBBB has been defined at this point, so everything between  this and the #endif is skipped
#endif

template <class T>
T B<T>::getVal(){
  return val;
}

#endif

template <class T>
T B<T>::getVal(){
  return val;
}

На данный момент я надеюсь, что очевидно, почему вы получаете ошибку: B.cpp:4:3: error: redefinition of ‘T B::getVal()’ T B::getVal(){.

Правильное исправление - просто поместить всю реализацию шаблонав шапке и избавьтесь от файла .cpp. Но если это не вариант из-за испорченного автомаркера, попробуйте добавить include-guards в файл .cpp. Но имейте в виду, что это плохая практика повсюду (.cpp файлы никогда не должны быть #include 'ed и, следовательно, никогда не должны включать include-guard), поэтому, если кто-то увидит ваш код, тогда будьте готовы ко многим вопросам иподнятые брови.

НО! Вероятно, первым шагом должно быть попытка поговорить с тем, кто дал вам задание, потому что здесь что-то не так;либо с помощью автоматического маркера, либо с вашим пониманием того, как это работает. Шаблонный класс должен , а не иметь .cpp файл (или он должен быть пустым).

0 голосов
/ 25 октября 2019

Вы никогда не должны #include ".cpp" в заголовках. Реализации шаблонов функций должны быть в заголовках, а не в cpp. В вашем примере A.cpp и B.cpp не нужны вообще. Если они по-прежнему требуются в задаче, сделайте их пустыми, за исключением директивы #include.

Редактировать: если вашему автомаркеру это не нравится, вы также можете попробовать встроить свои реализации, например,

template <class T>
class B{
public:
  T val;
  T getVal(){
     return val;
  }
};
...