C++(12) 模板类、模板继承(严格模式和自由模式)

文章目录

      • 模版类
        • 1. 模版类
        • 2. 模版参数限制
        • 3. 模版继承
          • 3.1 严格模式
          • 3.2 自由模式
        • 4. 模版类的模版函数
        • 5. 返回值类型带有模版

模版类

1. 模版类
#include 

using namespace std;

/*
当前 Person 类型,声明了连个模版分别对应
    NameType 模版类型,名称可以看出,用于约束成员变量 name 的类型
    AgeType  模版类型,名称可以看出,用于约束成员变量 age 的类型

模版类型充当数据类型占位符,在整个类中,成员变量,成员函数,构造函数都可以使用
*/
template 
class Person
{
public:
    Person() {}
    Person(NameType name, AgeType age) : name(name), age(age) {}
    Person(const Person & person) : name(person.name), age(person.age) {}
    ~Person() {}

    NameType getName() { return name; }
    void setName(NameType name) { this->name = name; }

    AgeType getAge() { return age; }
    void setAge(AgeType age) { this->age = age; }

private:
    NameType name;
    AgeType age;
};

int main(int argc, char const *argv[])
{
    /*
    Person 类型带有模版修饰,需要在使用之前明确模版对应的具体类型
    模版具备数据类型支持的多样性,同时一旦确定模版类型,严格遵守数据类型一致化原则

    Person 类型如何确定模版对应的具体数据类型
    格式:
    类名<模版对应具体数据类型> * 对象 = new 类型<模版对应具体数据类型>(...);
        Person
    */

    // p1 明确告知编译器 NameType ==> string AgeType ==> int
    // 在后续的代码中,通过 p1 调用 Person 类内函数按照以上规则完成
    Person *p1 = new Person();

    p1->setName("布丁");
    p1->setAge(3);

    cout << "Name : " << p1->getName() << ", Age : " << p1->getAge() << endl;

    Person *p2 = new Person("张三", 14);
    cout << "Name : " << p2->getName() << ", Age : " << p2->getAge() << endl;

    delete p1;
    delete p2;

    return 0;
}
2. 模版参数限制

双重限制

  • 限制外部类型
  • 限制模版类型
#include 

using namespace std;

template 
class Data
{
public:
    Data() {}
    Data(DataType value, MsgType msg) : value(value), msg(msg) {}
    Data(const Data &data) : value(data.value), msg(data.msg) {}
    ~Data() {}

    DataType getValue() { return value; }
    void setValue(DataType value) { this->value = value; }

    MsgType getMsg() { return msg; }
    void setMsg(MsgType msg) { this->msg = msg; }

private:
    DataType value;
    MsgType msg;
};

/*
当前 test1 函数明确告知调用者,当前所需的参数为 Data
同时限制 Data 中对应的模版类型为 
*/
void test1(Data *data);

/*
当前 test1 函数明确告知调用者,当前所需的参数为 Data
同时限制 Data 中对应的模版类型为 
*/
void test1(Data *data);

int main(int argc, char const *argv[])
{
    /*
    双重限制
    */
    Data *d1 = new Data(10, "别困!");
    Data *d2 = new Data(3.14, "别困!!");
    Data *d3 = new Data('G', "遵守数据类型一致化原则");

    test1(d1);
    test1(d2);
    /*
    test1 函数重载操作,所需函数有两种情况
        Data *
        Data *

    并没有支持
        Data * 考虑到双重限制,分别对应外部类型和模版类型
        因此 d3 无法作为函数 test1 的实际参数
        【注意】请遵守数据类型一致化原则
    */
    // test1(d3);

    delete d1;
    delete d2;
    delete d3;

    return 0;
}


void test1(Data *data)
{
    cout << "value : " << data->getValue() << ", Msg : " << data->getMsg() << endl;
}

void test1(Data *data)
{
    cout << "value : " << data->getValue() << ", Msg : " << data->getMsg() << endl;
}
3. 模版继承
3.1 严格模式
#include 

using namespace std;

/*
类带有模版,同时有子类继承当前类
    1. 自由模式
        子类带有和父类同名声明模版
    2. 严格模式【当前模式】
        子类在继承父类时,直接指定模版的具体类型,不得修改
*/

/*
MyCompare 类
    1. 声明了模版
    2. 声明纯虚函数
    3. MyCompare 是一个抽象类
*/
template 
class MyCompare
{
public:
    // 纯虚函数,并且使用了类声明的模版
    virtual bool compare(T t1, T t2) = 0;
};
/*
IntCompare 类
    1. 继承了 MyCompare 抽象类
    2. 继承父类的过程中,同时限制了模版对应的具体类型
    3. IntCompare 类没有声明模版

IntCompare 目标是一个【实现类】
    1. 必须实现 Compare 函数
    2. 父类 MyCompare 已经明确限制模版对应的具体类型为 int 类型
    3. IntCompare 目标实现的函数
        bool compare(int t1, int t2)
*/
class IntCompare : public MyCompare
{
public:
    bool compare(int t1, int t2)
    {
        return t1 > t2;
    }
};

int main(int argc, char const *argv[])
{
    /*
    bool compare(long t1, long t2) {...}
        在明确 模版对应的类型为 int 类型,实现上面的函数
        实例化的过程中,会出现报错:
        纯虚拟 函数 "MyCompare::compare [其中 T=int]" 没有强制替代项
    */
    IntCompare * ic = new IntCompare;

    cout << "ret : " << ic->compare(30, 20) << endl; // 1
    cout << "ret : " << ic->compare(10, 20) << endl; // 0

    return 0;
}
3.2 自由模式
#include 

using namespace std;

/*
类带有模版,同时有子类继承当前类
    1. 自由模式【当前模式】
        子类带有和父类同名声明模版
    2. 妻管严模式
        子类在继承父类时,直接指定模版的具体类型,不得修改
*/

/*
MyCompare 类
    1. 声明了模版
    2. 声明纯虚函数
    3. MyCompare 是一个抽象类
*/
template 
class BaseHandler
{
public:
    // 纯虚函数,并且使用了类名声明的模版
    virtual void handler(T t) = 0;
};

/*
MyHander 继承抽象类 BaseHandler,同时
    1. 声明和 BaseHandler 同名模版
    2. 当前模版类型尚未明确
    3. 必须实现 void hander(T t) 函数
*/
template 
class MyHandler : public BaseHandler
{
public:
    void handler(T t)
    {
        cout << "数据情况 : " << t << endl;
    }
};

int main(int argc, char const *argv[])
{
    // 实例化 MyHandler 类对象,需要指定模版对应的具体类型
    MyHandler * m1 = new MyHandler;
    m1->handler("零零零零");

    MyHandler * m2 = new MyHandler;
    m2->handler(14);

    delete m1;
    delete m2;

    return 0;
}
4. 模版类的模版函数
#include 

using namespace std;

template 
class Test
{
public:
    // 当前函数使用的模版为当前 Test 类声明的模版
    void handler(T t) { cout << "value : " << t << endl; }

    /*
    模版类内的函数,期望可以自定义模版,使用的模版数据形式,约束与当前类不同
    */
    template 
    void my(T2 t) { cout << "value : " << t << endl; }
};

int main(int argc, char const *argv[])
{
    Test * test = new Test;

    test->handler("零零零零");

    /*
    my 函数对应的模版类型,由实际参数决定,并不是实例化 Test 类型决定
    */
    test->my(3.14);

    return 0;
}

5. 返回值类型带有模版
#include 

using namespace std;

/*
K ==> Key   键
V ==> Value 值
*/
template 
class Data
{
public:
    Data() {}
    Data(K key, V value) : key(key), value(value) {}
    Data(const Data & data) : key(data.key), value(data.value) {}
    ~Data() {}

    K getKey() { return key; }
    void setKey(K key) { this->key = key; }

    V getValue() { return value; }
    void setValue(V value) { this->value = value; }

    /*
    友元函数中,重载运算符操作,使用的模版并不是 Data 声明的模版
    而是函数自定义模版,通过实际参数 Data 类型中的模版情况,
    限制当前函数的模版类型

    【满足注意 Data 类型展示数据操作】
    */
    template 
    friend ostream & operator<<(ostream & o, Data * data);

private:
    K key;
    V value;
};

template 
ostream & operator<<(ostream & o, Data * data)
{
    o << "Key : " << data->getKey() << ", Value : " << data->getValue();
    return o;
}

template 
Data *getData(K key, V value);

int main(int argc, char const *argv[])
{
    string name = "MY";
    Data * data = getData(name, 3);
    cout << data << endl;

    Data * data1 = getData(6.18, 9999);
    cout << data1 << endl;

    delete data;
    delete data1;

    return 0;
}

/*
外部函数自定义模版,返回值是 Data 类型,同时
利用当前函数的实际参数对 Data 中模版数据进行
约束限制,模版具体数据情况根据参数具体数据类型确定!
*/
template 
Data * getData(K key, V value)
{
    return new Data(key, value);
}

你可能感兴趣的:(c++,开发语言,c语言,学习,经验分享)