C++模板(二)

本文详细介绍了C++中类模板的使用,包括通用栈、数组和队列的实现,以及非类型模板参数的概念,特别强调了非类型模板参数的限制和注意事项。
摘要由CSDN通过智能技术生成

前言:

上一篇介绍了c++模板的简单使用, 这一篇将介绍一下c++类模板

先看一段代码:

#include <iostream>
#include <vector>

template<typename T>
class Stack {
private:
    std::vector<T> elements;

public:
    void push(const T& element) {
        elements.push_back(element);
    }

    void pop() {
        if (!elements.empty()) {
            elements.pop_back();
        }
    }

    T& top() {
        if (!elements.empty()) {
            return elements.back();
        }
        throw std::out_of_range("Stack<>::top(): empty stack");
    }

    bool empty() const {
        return elements.empty();
    }
};

int main() {
    // 使用Stack模板创建一个整数栈
    Stack<int> intStack;
    intStack.push(1);
    intStack.push(2);
    intStack.push(3);

    while (!intStack.empty()) {
        std::cout << intStack.top() << " ";
        intStack.pop();
    }
    std::cout << std::endl;

    // 使用Stack模板创建一个字符栈
    Stack<char> charStack;
    charStack.push('a');
    charStack.push('b');
    charStack.push('c');

    while (!charStack.empty()) {
        std::cout << charStack.top() << " ";
        charStack.pop();
    }
    std::cout << std::endl;

    return 0;
}

这是一个简单的C++类模板示例,实现了一个通用的栈数据结构,其中Stack 类模板接受一个模板参数 T,它表示栈中存储的元素类型。可以通过 Stack<int>Stack<char> 来实例化具体的栈类。这样就可以像使用普通的栈一样使用这些实例化的对象。

接下来看看非类型模板参数的模板类:

#include <iostream>

template<int Size>
class Array {
private:
    int data[Size];

public:
    void set(int index, int value) {
        if (index >= 0 && index < Size) {
            data[index] = value;
        } else {
            std::cerr << "Index out of range" << std::endl;
        }
    }

    int get(int index) const {
        if (index >= 0 && index < Size) {
            return data[index];
        } else {
            std::cerr << "Index out of range" << std::endl;
            return -1; // or throw an exception
        }
    }
};

int main() {
    // 使用模板类Array创建一个包含5个整数的数组
    Array<5> intArray;

    // 设置和获取数组元素
    for (int i = 0; i < 5; ++i) {
        intArray.set(i, i * 10);
    }

    for (int i = 0; i < 5; ++i) {
        std::cout << "Element at index " << i << ": " << intArray.get(i) << std::endl;
    }

    return 0;
}

非类型模板参数可以将常量表达式作为模板参数传递给模板类。这使得在编译时能确定一些值,而不是在运行时。非类型模板参数可以是整数、枚举、指针或引用。在这个示例中,Array 是一个模板类,它接受一个非类型模板参数 Size,表示数组的大小。在 main() 函数中,我们使用 Array<5> 实例化了一个包含5个整数的数组。因此,Size 在这个实例中被设置为5。然后我们设置了数组的元素并进行了输出。

一个模板类能同时具有类型模板参数和非类型模板参数,看下面这个案例:

#include <iostream>

template<typename T, int Capacity>
class Queue {
private:
    T data[Capacity];
    int frontIndex;
    int rearIndex;

public:
    Queue() : frontIndex(0), rearIndex(0) {}

    void enqueue(const T& item) {
        if (rearIndex < Capacity) {
            data[rearIndex++] = item;
        } else {
            std::cerr << "Queue is full. Unable to enqueue." << std::endl;
        }
    }

    T dequeue() {
        if (frontIndex < rearIndex) {
            return data[frontIndex++];
        } else {
            std::cerr << "Queue is empty. Unable to dequeue." << std::endl;
            return T(); // default value for T
        }
    }

    bool isEmpty() const {
        return frontIndex == rearIndex;
    }

    bool isFull() const {
        return rearIndex == Capacity;
    }
};

int main() {
    // 创建一个容量为5的整数队列
    Queue<int, 5> intQueue;

    // 将一些整数入队
    for (int i = 1; i <= 5; ++i) {
        intQueue.enqueue(i * 10);
    }

    // 出队并输出元素
    while (!intQueue.isEmpty()) {
        std::cout << "Dequeued: " << intQueue.dequeue() << std::endl;
    }

    // 尝试向已满的队列添加元素
    for (int i = 1; i <= 6; ++i) {
        intQueue.enqueue(i * 10);
    }

    return 0;
}

它以类型和一个常量值作为参数,在这个示例中,Queue 是一个模板类,它有两个模板参数:T 表示存储在队列中的元素类型,Capacity 表示队列的容量。在 main() 函数中,我们使用 Queue<int, 5> 创建了一个容量为5的整数队列。然后我们将一些整数入队,并出队并输出它们。最后,我们尝试向已满的队列添加元素,观察错误消息。

不过使用非类型模板时需要注意参数类型,

非类型模板参数不能是以下类型:

  1. 浮点数类型:浮点数运算通常涉及到复杂的计算和比较操作,在编译时确定浮点数值可能会导致不确定性和不稳定性,因此C++标准规定不允许使用浮点数类型作为非类型模板参数。

  2. 非常量表达式类型:非类型模板参数必须在编译时被确定,而运行时的变量是无法满足这一要求的。如果允许运行时变量作为非类型模板参数,会导致模板实例化的不确定性和可移植性问题。

  3. 字符串类型:C++标准中没有直接支持字符串作为非类型模板参数的机制。字符串的长度和内容可能是变化的,在编译时确定字符串值的复杂性和不确定性会导致编译器难以处理。

  4. 类类型:模板的非类型参数必须是在编译时可确定的常量表达式,而对象是在运行时创建的。如果允许类类型作为非类型模板参数,就会涉及到对象的创建和析构等操作,这是在编译时无法完成的。

  5. 非静态成员指针类型:非静态成员函数指针涉及到类的实例,而模板实例化时并不会生成类的实例,因此无法使用非静态成员函数指针作为非类型模板参数。

  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值