dachte ich, eine explizite Anfrage Instanziierung automatisch alle Basisklassenmitglieder auch instanziiert würde, aber ich bekomme einen linker error: unresolved external symbol "public: void Base<int>::foo(int)"
beim Bau dieses Code Visual Studio 2008 oder 2010Explizite Instanziierungen von C++ - Klassenvorlagen instanziieren Abhängige Basisklassen?
Hinweis verwenden, um einen Anruf zu foo()
innerhalb bar()
zwingt den Compiler Hinzufügen instanziieren Base<int>::bar()
und der Build ist erfolgreich, so scheint es, dass der Compiler über alle notwendigen Informationen verfügt, um foo()
instanziieren.
Offensichtlich instanziieren Base<int>
in source.cpp explizit das Instanziieren des Builds, aber es scheint albern, alle abhängigen Basisklassen explizit zu instanziieren, wenn eine abgeleitete Klasse explizit instanziiert wird.
Ist das normal? Ich konnte nicht finden, was der Standard zu diesem Thema sagt.
header.h
template<typename T>
class Base {
public:
void foo();
};
template<typename T>
class Derived : public Base<T> {
public:
void bar();
};
source.cpp
#include "header.h"
template<typename T>
void Base<T>::foo() { }
template<typename T>
void Derived<T>::bar() {
// this->foo(); // adding this forces instantiation of foo()???
}
template class Derived<int>;
main.cpp
#include "header.h"
int main() {
Derived<int> d;
d.foo(); // Linker Error: unresolved external symbol "public: void Base<int>::foo(int)"
}
Bearbeiten:
Es sieht aus wie der Standard sagt, nur Mitglieder einer Klasse werden durch eine explizite Klasseninstanziierung instanziiert, so dass der Linker-Fehler in meinem Beispiel gerechtfertigt ist.
beachten, dass eine Klasse von Klasse-Kopf definiert ist {Mitglied-Spezifikation} und „Die Element-Spezifikation in einer Klassendefinition deklariert die vollständige Reihe von Mitgliedern der Klasse, kann kein Mitglied andere Stelle hinzugefügt werden.“ So befinden sich Mitglieder nur zwischen den geschweiften Klammern {}, und Mitglieder der öffentlichen Basisklasse werden nicht Mitglieder der abgeleiteten Klasse, sie sind lediglich von der abgeleiteten Klasse oder von Objekten der abgeleiteten Klasse zugänglich.
Meine einzige verbleibende Frage ist, warum der Standard angibt, dass die explizite Instantiierung einer Klassenvorlage nur Mitglieder und nicht Mitglieder von Basisklassen instanziiert? Meine Vermutung ist, dass dies eine bessere Kontrolle dessen ermöglicht, was explizit wo instanziiert wird. Jemand, der explizite Vorlagenklasseninstanziierungen verwendet, würde höchstwahrscheinlich die Basisklassendefinitionen in einer anderen Datei als die abgeleiteten Klassendefinitionen haben und diese explizit separat instanziieren.
Fügt ein expliziter Konstruktor für abgeleitete Triggerinstanziierung der Basisklasse hinzu? Ich vermute, dass der Compiler versucht, nicht mehr zu tun als nötig. Wenn Sie einen Konstruktor haben, könnte er erkennen, dass er auch Base erstellen muss, und das könnte ihn auslösen. Hast du auch gcc oder andere Compiler ausprobiert? –
Das Hinzufügen eines Konstruktors mit oder ohne Argument und mit oder ohne Schlüsselwort "explizit" löst keine Instanziierung der Basisklasse foo() aus, aber ein Aufruf von foo() aus der abgeleiteten Elementleiste() löst die implizite Instanziierung aus. – JohnPS