La clase templada con una base no plantilla me da un error LNK2005
-
28-10-2019 - |
Pregunta
Tengo una clase plantada Niño que hereda de una no templada Padre clase. Cuando incluyo NiñoEl encabezado de múltiples archivos .cpp obtengo un error LNK2005. Esto sucede porque Padre se define en múltiples unidades de compilación. Cuando esas unidades se unen, causan el error LNK2005.
En caso de que se lo pregunte, el propósito de Padre es dar Niño una variable estática para todos Niño instancia, no solo uno para cada Niño <'' tipo ''>>.
Mi pregunta es, ¿cómo creo una clase plantada que tiene un único (en todo Niño instancias) variable estática y se puede incluir en múltiples archivos .cpp?
Aquí hay un ejemplo de juguete que causa este error LNK2005:
main.cpp
#include "Apple.h"
#include "Banana.h"
#include <string>
void main() {
Apple apple;
Banana banana;
}
Apple.h
#ifndef APPLE_H
#define APPLE_H
struct Apple {
Apple();
};
#endif // APPLE_H
Apple.cpp
#include "Apple.h"
#include "Child.h"
Apple::Apple() {
Child<int> child;
child.foo(5);
}
Plátano.h
#ifndef BANANA_H
#define BANANA_H
struct Banana {
Banana();
};
#endif // BANANA_H
Banana.cpp
#include "Banana.h"
#include "Child.h"
Banana::Banana() {
Child<double> child;
child.foo(3.14);
}
Niño. H
#ifndef CHILD_H
#define CHILD_H
#include <iostream>
using namespace std;
///////////// Parent Class Def ///////////
class Parent {
protected:
static int id;
};
int Parent::id = 0;
///////////// Child Class Def ///////////
template <class T>
struct Child : protected Parent {
Child();
void foo(T t);
};
template <class T>
Child<T>::Child() {
id++;
}
template <class T>
void Child<T>::foo(T t) {
cout << "Child" << id << "'s foo() says: " << t << endl;
}
#endif // CHILD_H
Error LNK2005: "Protegido: static int
Solución
Necesitas definir int Parent::id = 0;
Solo una vez en Child.C
. Al incluirlo en el encabezado se define una vez por archivo que incluye su encabezado.
Supongo que debo tener en cuenta que entre los males de ponerlo en Parent.C
(nombre de clase coincidente) o Child.C
Al igualar el nombre del encabezado, elegí la consistencia. Mucho mejor es poner Parent
en sus propios archivos para que pueda poner la definición en un apropiado nombrado Parent.C
que todavía coincide con el nombre del encabezado correspondiente.
Otros consejos
Jalar
int Parent::id = 0;
hacia Parent.cpp
Y estarás bien. Lo que sucede ahora es que la definición se incluye una vez por unidad de traducción que incluye Child.h
.