2017-01-02 1 views
3

In einem meiner Projekte habe ich eine Baumdatenstruktur, die Werte eines generischen Typs T enthalten könnte.Reduzieren Sie die Kompilierungszeiten und Abhängigkeiten mit der Friend-Klasse

Um Kompilierungszeiten und Abhängigkeiten zu reduzieren, habe ich versucht, Implementierungsdetails aus der Baumknotenklasse Node in die Klasse NodeImpl zu verschieben. Die Interna von Node sind privat und sollten nur an definierten Einsprungpunkten, zB durch die getName Funktion, aufgerufen werden.

Nur Personen, die an der Verwendung von getName interessiert sind, sollten NodeImpl in ihren Quelldateien enthalten. So denke ich, meine Kompilierzeiten und Abhängigkeiten zu reduzieren.

Aber aus irgendeinem Grund werden die folgenden drei Spielklassen nicht kompilieren. Es gibt keinen Zugriff auf private Mitglieder. Was mache ich falsch?

Datei main.cpp:

#include <iostream> 
#include "Node.h" 
#include "NodeImpl.h" 

int main(int argc, char** args) { 
    Node<int> n("Test", 2); 
    std::cout << getName(n) << std::endl; 
} 

Datei Node.h:

#pragma once 
#include <string> 

template<typename T> 
class NodeImpl; 

template<typename T> 
class Node { 
public: 
    typedef T value_type; 
    Node(const std::string& name, const T& value) : name(name), value(value) {} 

private: 
    std::string name; 
    T value; 
    friend class NodeImpl<T>; 
}; 

Datei NodeImpl.h:

#pragma once 
#include "Node.h" 

template<typename T> 
std::string getName(Node<T>& n); 

template<typename T> 
class NodeImpl { 
    NodeImpl(Node<T>& node) : mNode(node) { 
    } 
    Node<T>& mNode; 

    std::string name() { 
     return mNode.name; 
    } 

    friend std::string getName(Node<T>& n); 
}; 

template<typename T> 
std::string getName(Node<T>& n) { 
    auto x = NodeImpl<T>(n); 
    return x.name(); 
} 
+5

Freunde deiner Freunde sind nicht deine Freunde – Danh

+0

Danke für die Hilfe. Natürlich ist die Freundschaftsdeklaration nicht transitiv. Ich habe 'NodeImpl.h' geändert. Dachte, das war die Lösung. Aber es kompiliert immer noch nicht. :-( – Aleph0

Antwort

2

Die warning produced by GCC gibt Einblick:

warning: friend declaration 'std::__cxx11::string getName(Node<T>&)' declares a non-template function [-Wnon-template-friend] 
friend std::string getName(Node<T>& n); 
            ^
note: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here) 

Mit anderen Worten: Ihre Klasse NodeImpl<int> wurde befriending eine globale Funktion std::string getName(Node<int> &), die mit der Funktion nicht verwandt ist std::string getName<int>(Node<int> &) von der Funktionsvorlage instanziiert template <class T> std::string getName(Node<T> &) für T = int.

So ist die richtige Lösung ist dies:

template<typename T> 
class NodeImpl { 
    // ... as before ... 

    friend std::string getName<T>(Node<T>& n); 
}; 

Diese [live example] zeigt, dass diese Lösung in der Tat funktioniert.

+0

Das ist so erstaunlich. Ich benutze Visual Studio. Vielen Dank. :-) – Aleph0

Verwandte Themen