2017-01-02 86 views
3

在我的一個項目中,我有一個樹型數據結構,它可能包含一個通用類型的值T使用朋友類減少編譯時間和依賴關係

爲了減少編譯時間和依賴關係,我嘗試將實現細節從樹節點類Node移動到類NodeImplNode的內部是私有的,只能在定義的入口點訪問,例如getName函數。

只有對使用getName感興趣的用戶應在其源文件中包含NodeImpl。這是我想如何減少編譯時間和依賴關係。

但由於某些原因,以下三種玩具類將無法編譯。它說沒有訪問私人成員。我做錯了什麼?

文件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; 
} 

文件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>; 
}; 

文件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

你朋友的朋友不是你的朋友 – Danh

+0

感謝您的幫助。當然,朋友聲明不是傳遞性的。我改變了'NodeImpl.h'。認爲這是解決方案。但仍然沒有編譯。 :-( – Aleph0

回答

2

warning produced by GCC讓用戶深入瞭解:

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) 

換句話說,你NodeImpl<int>類是結交一個全局函數std::string getName(Node<int> &),這是不相關的,從函數模板template <class T> std::string getName(Node<T> &)實例化T = int功能std::string getName<int>(Node<int> &)

所以正確的方法是這樣的:

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

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

[live example]表明,該解決方案確實有效。

+0

那真是太神奇了,我在使用Visual Studio,非常感謝。:-) – Aleph0