欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

C++模板-36-类模板和继承和友元

程序员文章站 2022-07-10 21:29:09
这里来学习下类模板作为父类,那么子类继承父类是有问题,这种问题是什么,如何解决。然后看看类模板配合友元函数的类内实现和类外实现。1.类模板和继承如果父类是一个模板类,子类继承的时候会有下面几个点需要注意当子类继承的父类是一个类模板时,子类在声明的时候,要指定出父类中T的类型如果不指定,编译器无法给与子类分配内存如果想灵活指定出父类中T的类型,子类也需要为类模板先用代码演示1,2点,如果不指定父类T的类型,这个编译错误是什么#include ....

这里来学习下类模板作为父类,那么子类继承父类是有问题,这种问题是什么,如何解决。然后看看类模板配合友元函数的类内实现和类外实现。

 

1.类模板和继承

如果父类是一个模板类,子类继承的时候会有下面几个点需要注意

  1. 当子类继承的父类是一个类模板时,子类在声明的时候,要指定出父类中T的类型
  2. 如果不指定,编译器无法给与子类分配内存
  3. 如果想灵活指定出父类中T的类型,子类也需要为类模板

先用代码演示1,2点,如果不指定父类T的类型,这个编译错误是什么

#include <iostream>
#include <string>
using namespace std;

//类模板
template <class T>
class Base
{
    T m;
};

// 子类
class Sun : public Base
{


};


void test01()
{
    
}

int main()
{
    test01();
    system("pause");
    return 0;
}

上面代码在13行 Base这里会报错,内容是“缺少 类模板 "Base" 的参数列表”,所以这里不能直接继承。因为编译器无法分配内存,我们知道一个空的类对象是4字节的大小内存,但是子类不知道父类T的类型,所以成员变量没法知道大小,从而无法分配内存。例如父类T m 由于数据类型不同,内存大小是不同的。

 

2. 把子类也写成模板,灵活继承父类

如果要灵活使用父类这种模板类,子类也需要改成模板类。

#include <iostream>
#include <string>
using namespace std;

//类模板
template <class T>
class Base
{
    T m;
};

// 子类
template <class T1, class T2>
class Sun : public Base<T2>
{
    

};


void test01()
{
    
}

int main()
{
    test01();
    system("pause");
    return 0;
}

还是在13 14行,T1表示子类中继承下来的m的类型, T2表示父类中m的类型。

 

3.友元函数配合模板类内实现

先复习下什么是友元,就是使用关键字friend,告诉编译器,可以访问这个类下的私有成员变量和函数。例如下面定义这个全局函数就是friend修饰,就可以通过传入对象p进行访问到Person类的私有成员m_Name和m_Age。

#include <iostream>
#include <string>
using namespace std;

//类模板
template <class T1, class T2>
class Person
{
    // 全局函数
    friend void printPerson(Person<T1, T2> p)
    {
        cout << "姓名:" << p.m_Name << " 年龄:" << p.m_Age << endl;

    }

public:
    Person(T1 name,T2 age)
    {
        this->m_Name = name;
        this->m_Age = age;
    }

private:
    T1 m_Name;
    T2 m_Age;
};


void test01()
{
    Person<string, int>p("Anthony", 18);
    printPerson(p);
}

int main()
{
    test01();
    system("pause");
    return 0;
}

友元在模板类中实现很简单,直接在类内就实现。接下来如何看使用友元,但是模板类的成员函数是在类外实现。

#include <iostream>
#include <string>
using namespace std;

// 类外实现
template <class T1, class T2>
class Person;

// 告诉编译器这是一个模板函数
template <class T1, class T2>
void printPerson(Person<T1, T2> p)
{
    cout << "姓名:" << p.m_Name << " 年龄:" << p.m_Age << endl;
}

//类模板
template <class T1, class T2>
class Person
{
    // 全局函数类外实现
    friend void printPerson<>(Person<T1, T2> p);
   
public:
    Person(T1 name,T2 age)
    {
        this->m_Name = name;
        this->m_Age = age;
    }

private:
    T1 m_Name;
    T2 m_Age;
};

void test01()
{
    Person<string, int>p("Anthony", 18);
    printPerson(p);
}

int main()
{
    test01();
    system("pause");
    return 0;
}

全局函数类外实现比较复杂,第一 类模板声明放前面,告诉编译器Person是模板类,第二 全局函数实现也放前面,也是让编译器提前知道有这个全局函数,第三 类内部全局函数声明,其中加<>表示这个全局函数已经不是一个普通函数,而是变成一个模板函数。

 

 

本文地址:https://blog.csdn.net/u011541946/article/details/107349604