zoukankan      html  css  js  c++  java
  • c++类模板之间友元函数调用

     1 #include <stdio.h>
     2 #include <iostream>
     3 
     4 using namespace std;
     5 
     6 template<typename T> class BTree;
     7 
     8 /***************************节点类模板*********************************/
     9 template<typename T>
    10 class BTreeNode{
    11     friend void BTree<T>::Print(BTreeNode<T> *t);
    12     friend void BTree<T>::PreOrder(BTreeNode<T> *t);
    13     friend int BTree<T>::Deepth(BTreeNode<T> *t);
    14     friend void BTree<T>::Insert(BTreeNode<T> *t, int n);
    15 
    16 public:
    17     BTreeNode(){ data = NULL; left = right = NULL; }
    18     BTreeNode(const T& val){ data = val; left = right = NULL; }
    19     BTreeNode(const T& val, BTreeNode<T> *l, BTreeNode<T> *r){ data = val; left = l; right = r; }
    20     ~BTreeNode(){ delete left; delete right; }
    21 
    22 private:
    23     T data;
    24     BTreeNode<T> *left;
    25     BTreeNode<T> *right;
    26 };
    27 
    28 /***************************树类模板**********************************/
    29 template<typename T>
    30 class BTree{
    31 public:
    32     void Print(BTreeNode<T> *t);
    33     void PreOrder(BTreeNode<T> *t);
    34     int Deepth(BTreeNode<T> *t);
    35     void Insert(BTreeNode<T> *t,int n);
    36 private:
    37     BTreeNode<T> *root;
    38 };
    39 
    40 template<typename T>
    41 void BTree<T>::Print(BTreeNode<T> *t)
    42 {
    43     cout << t->data << endl;
    44 }
    45 
    46 
    47 template<typename T> 
    48 void BTree<T>::PreOrder(BTreeNode<T> *t)
    49 {
    50     if (t != NULL)
    51     {
    52         Print(t);
    53         PreOrder(t->left);
    54         PreOrder(t->right);
    55     }
    56 }
    57 
    58 template<typename T> 
    59 int BTree<T>::Deepth(BTreeNode<T> *t)
    60 {
    61     if (t == NULL)
    62     {
    63         return 0;
    64     }
    65     int left = 1;
    66     int right = 1;
    67     left += Deepth(t->left);
    68     right += Deepth(t->right);
    69     return left >= right ? left : right;
    70 }
    71 
    72 //右边的节点比左边大10
    73 template<typename T>
    74 void BTree<T>::Insert(BTreeNode<T> *t, int n)
    75 {
    76     if (n < 0)
    77     {
    78         return;
    79     }
    80     int i = ii;
    81     t->left = new BTreeNode<T>(ii++);
    82     //i = ii;
    83     Insert(t->left, n - 1);
    84     t->right = new BTreeNode<T>(i + 10);
    85     Insert(t->right, n - 1);
    86 }

    友元函数可以访问封装好的类的私有成员,无疑破坏了类的封装性。不过确实可以提高很多发开的效率。
    以前用c语言写链表等,都用结构体来定义一个点。在c++中,用类代替了结构体:确实,类和结构体差不多,只是类可以有私有变量,而结构体都是公有的。
    在写二叉树时发现了这样写需要注意的。
    代码在上面。main就不写了。
    首先要写一个节点类:
    /***************************节点类模板*********************************/
    template<typename T>
    class BTreeNode{
        friend void BTree<T>::Print(BTreeNode<T> *t);
        friend void BTree<T>::PreOrder(BTreeNode<T> *t);
        friend int BTree<T>::Deepth(BTreeNode<T> *t);
        friend void BTree<T>::Insert(BTreeNode<T> *t, int n);
    
    public:
        BTreeNode(){ data = NULL; left = right = NULL; }
        BTreeNode(const T& val){ data = val; left = right = NULL; }
        BTreeNode(const T& val, BTreeNode<T> *l, BTreeNode<T> *r){ data = val; left = l; right = r; }
        ~BTreeNode(){ delete left; delete right; }
    
    private:
        T data;
        BTreeNode<T> *left;
        BTreeNode<T> *right;
    };

    除了基本的声明,再声明几个友元函数给之后的BTree类调用,BTreeNode只是表示节点,而树是很多节点相连的。所以下面写BTree类,实现树的一些功能。需要注意的是:声明友元的时候,不能跟普通的外部函数一样,声明类或类模板的函数,需要加上域的限制。想想也是,否则编译器怎么能之后你要调用到底是哪个函数呢?因为假如在类内还类外都有同一个名字的函数,那就出事了。所以限定域肯定是有的!!!

    /***************************树类模板**********************************/
    template<typename T>
    class BTree{
    public:
        void Print(BTreeNode<T> *t);
        void PreOrder(BTreeNode<T> *t);
        int Deepth(BTreeNode<T> *t);
        void Insert(BTreeNode<T> *t,int n);
    private:
        BTreeNode<T> *root;
    };
    
    template<typename T>
    void BTree<T>::Print(BTreeNode<T> *t)
    {
        cout << t->data << endl;
    }
    
    
    template<typename T> 
    void BTree<T>::PreOrder(BTreeNode<T> *t)
    {
        if (t != NULL)
        {
            Print(t);
            PreOrder(t->left);
            PreOrder(t->right);
        }
    }
    
    template<typename T> 
    int BTree<T>::Deepth(BTreeNode<T> *t)
    {
        if (t == NULL)
        {
            return 0;
        }
        int left = 1;
        int right = 1;
        left += Deepth(t->left);
        right += Deepth(t->right);
        return left >= right ? left : right;
    }
    
    //右边的节点比左边大10
    template<typename T>
    void BTree<T>::Insert(BTreeNode<T> *t, int n)
    {
        if (n < 0)
        {
            return;
        }
        int i = ii;
        t->left = new BTreeNode<T>(ii++);
        //i = ii;
        Insert(t->left, n - 1);
        t->right = new BTreeNode<T>(i + 10);
        Insert(t->right, n - 1);
    }

    可以看到,在类模板里还是跟正常一样声明函数,和在类外定义函数。但是当你在主函数使用这些定义的函数就会出错。那是因为在定义友元的时候没有声明类模板。

    在第一个类模板就是BTreeNode之前就上很重要的一句:

    template<typename T> class BTree;

    就完美了。另外记住:以后在使用之前先声明,否则无论是使用和定义都会出现问题。

    我写程序一直都是class什么,class什么,int main()什么。其实先写定义头是个好习惯!!!

  • 相关阅读:
    POJ3094 UVALive3594 HDU2734 ZOJ2812 Quicksum【进制】
    UVALive5583 UVA562 Dividing coins
    POJ1979 HDU1312 Red and Black【DFS】
    POJ1979 HDU1312 Red and Black【DFS】
    POJ2386 Lake Counting【DFS】
    POJ2386 Lake Counting【DFS】
    HDU4394 Digital Square
    HDU4394 Digital Square
    UVA213 UVALive5152 Message Decoding
    UVA213 UVALive5152 Message Decoding
  • 原文地址:https://www.cnblogs.com/wyc199288/p/4989851.html
Copyright © 2011-2022 走看看