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()什么。其实先写定义头是个好习惯!!!

时间: 2024-10-17 00:53:08

c++类模板之间友元函数调用的相关文章

类模板,多种类型的类模板,自定义类模板,类模板的默认类型,数组的模板实现,友元和类模板,友元函数,类模板与静态变量,类模板与普通类之间互相继承,类模板作为模板参数,类嵌套,类模板嵌套,类包装器

 1.第一个最简单的类模板案例 #include "mainwindow.h" #include <QApplication> #include <QPushButton> #include <QLabel> template<class T> class run { public: T w; void show() { w.show(); } void settext() { w.setText("A"); }

类模板的友元

详见http://www.cnblogs.com/assemble8086/archive/2011/10/02/2198308.html 类模板的友元有三种声明: 1)非模板类的友元类或友元函数 1 template <typename T> 2 class Rect{ 3 public: 4 friend void create(); 5 }; create函数成为所有Rect类实例化的友元,它可以访问全局对象;可以使用全局指针访问非全局对象;可以创建自己的对象;可以访问独立对象的模板类的

编程算法 - 不能被继承的类(模板参数友元) 代码(C++)

不能被继承的类(模板参数友元) 代码(C++) 本文地址: http://blog.csdn.net/caroline_wendy 题目: 用C++设计一个不能被继承的类. 可以使用模板类模板参数友元, 模板类私有构造函数, 类虚继承这个模板类, 如果类被其他类继承时, 则虚继承会直接调用模板类, 无法构造. 代码: /* * main.cpp * * Created on: 2014.7.13 * Author: Spike */ /*eclipse cdt, gcc 4.8.1*/ #inc

C++学习笔记(2)----类模板和友元

当一个类包含一个友元声明时,类与友元各自是否是模板是相互无关的.如果一个类模板包含一个非模板友元,则友元被授权可以访问所有模板实例.如果友元自身是模板,类可以授权给所有友元模板实例,也可以只授权给特定实例. 1. 一对一友好关系 类模板与另一个(类或函数)模板间友好关系的最常见形式是建立对应实例及其友元间的友好关系.例如,我们的 Blob 类应该讲 BlobPtr 类和一个模板版本的 Blob 相等运算符定义为友元. 为了引用(类或函数) 模板的一个特定实例,我们必须首先声明模板自身.一个模板声

关于类模板的友元函数

转载 http://blog.sina.com.cn/s/blog_69dd1a090101fc59.html 问题始于学习数据结构,自己编写一个单链表,其中用到了重载输出运算符<<,我写的大约这样: 1 template <class T> class List{ 2 friend std::ostream& operator << (std::ostream& os,const List<T>& slist); 3 //…… 4

【C/C++学院】0825-类模板/final_override/类模板与普通类的派生类模板虚函数抽象模板类/类模板友元/位运算算法以及类声明/Rtti 实时类型检测/高级new创建/类以及函数包装器

类模板 类模板多个类型默认类型简单数组模板 #pragma once template <class T=int>//类模板可以有一个默认的值 class myArray { public: myArray(); ~myArray(); }; #include "myArray.h" template <class T=int>//每一个函数都需要加上一个默认的值 myArray<T>::myArray() //类模板成员函数在外部,需要加载类型初始

类模板 友元重载形式 各种运算符重载 new delete ++ = +=

今天的重载是基于C++ 类模板的,如果需要非类模板的重载的朋友可以把类模板拿掉,同样可以参考,谢谢. 一.类模板中的友元重载 本人喜好类声明与类成员实现分开写的代码风格,如若您喜欢将类成员函数的实现写在类声明中,那么可以跳过该部分. 请看下面这段代码: 头文件: #pragma once template<typename T> class CLA { T m_value; public: CLA(const T&); friend CLA operator+(const CLA&am

C++ Primer 学习笔记_81_模板与泛型编程 --类模板成员[续1]

模板与泛型编程 --类模板成员[续1] 二.非类型形参的模板实参 template <int hi,int wid> class Screen { public: Screen():screen(hi * wid,'#'), cursor(hi * wid),height(hi),width(wid) {} //.. private: std::string screen; std::string::size_type cursor; std::string::size_type height

C++中的类模板详细讲述

一.类模板定义及实例化 1. 定义一个类模板: 1 template<class 模板参数表>2 3 class 类名{4 5 // 类定义......6 7 }: 其中,template 是声明类模板的关键字,表示声明一个模板,模板参数可以是一个,也可以是多个,可以是类型参数 ,也可以是非类型参数.类型参数由关键字class或typename及其后面的标识符构成.非类型参数由一个普通参数构成,代表模板定义中的一个常量. 例: 1 template<class type,int widt