C++学习笔记——私有继承、多重继承、类模板

目录

一、私有继承

二、多重继承

三、类模板

四、一个使用私有继承的示例代码

4.1代码

4.2输出结果

五、多重继承案列

六、类模板案例


C++中的继承和模板是非常强大和灵活的特性,它们可以帮助我们实现代码复用、抽象和泛化等目标。本文将着重介绍私有继承、多重继承和类模板这三个C++中比较重要的特性。

一、私有继承

私有继承是一种比较特殊的继承方式,它在语法上与公有继承和保护继承没有太大区别,但是其继承关系所暴露的接口和成员变量都会被隐藏起来,只有派生类自己可以访问到基类的成员。在使用私有继承时,我们通常会借助基类指针或引用来访问基类的成员,而不会直接使用派生类对象。

私有继承的应用场景比较广泛,例如可以用来实现"has-a"关系、模块化设计等。具体来说,如果一个类需要另一个类的部分功能,但是不想公开其接口,可以使用私有继承。此外,私有继承也可以用来防止基类的成员被误操作或滥用,从而提高代码的安全性。

二、多重继承

多重继承是C++中比较复杂和容易出现问题的特性之一,它允许一个派生类同时继承多个基类。多重继承在语法上并不复杂,但是在设计和实现上需要考虑一些问题,例如可能会出现菱形继承问题、基类构造函数的调用顺序等。因此在使用多重继承时需要谨慎考虑其适用性和实现细节。

多重继承的应用场景也比较广泛,例如可以用来实现多态、功能组合等。具体来说,如果一个类需要具有多种不同的特性或行为,可以使用多重继承来组合多个基类。此外,多重继承也可以用来实现接口继承和实现继承的分离,从而更好地实现面向对象的编程思想。

三、类模板

类模板是C++中非常强大和灵活的特性,它允许我们通过一个通用的模板来生成多个具体的类。类模板在定义时需要指定模板参数,这些参数可以是类型、常量、模板等等。类模板可以用来实现泛型编程、容器和算法库等。

类模板的语法比较复杂,但是理解一些基本概念后就可以轻松地应用它们。例如,我们可以使用模板参数来定义成员变量和成员函数,或者使用特化(partial specialization)和偏特化(full specialization)来针对不同的情况实现不同的行为。此外,C++11及以上版本还提供了可变参数模板(variadic template)和模板别名(template alias)等新特性,使得类模板的应用更加灵活和便捷。

私有继承是指派生类以 private 访问权限继承基类的成员。这意味着派生类无法直接访问基类的成员,只能通过基类指针或引用来访问。

四、一个使用私有继承的示例代码

4.1代码

#include <iostream>

class Base {
public:
    void display() {
        std::cout << "Base class" << std::endl;
    }
};

class Derived : private Base {
public:
    void showMessage() {
        display();  // 通过基类指针访问基类的成员函数
    }
};

int main() {
    Derived derived;
    derived.showMessage();
    return 0;
}

在这个示例中,Derived 类私有继承 Base 类。Derived 类中的 showMessage() 函数通过基类指针调用了 Base 类的 display() 函数。

4.2输出结果

Base class

私有继承主要用于实现类与类之间的"has-a"关系,即一个类包含另一个类的对象作为其成员。

五、多重继承案列

多重继承是指派生类可以同时继承多个基类。在多重继承中,派生类可以分别指定不同的继承方式(public、protected 或 private)来控制基类成员的访问权限。

下面是一个使用多重继承的示例代码:

#include <iostream>

class Base1 {
public:
    void display1() {
        std::cout << "Base1 class" << std::endl;
    }
};

class Base2 {
public:
    void display2() {
        std::cout << "Base2 class" << std::endl;
    }
};

class Derived : public Base1, private Base2 {
public:
    void showMessage() {
        display1();  // 通过派生类直接访问公有基类的成员函数
        //display2();  // 错误!无法直接访问私有基类的成员函数
    }
};

int main() {
    Derived derived;
    derived.showMessage();
    return 0;
}

在这个示例中,Derived 类同时继承了 Base1Base2 两个基类。Derived 类中的 showMessage() 函数可以直接调用 Base1 类的 display1() 函数,但无法直接调用 Base2 类的 display2() 函数。

输出结果为:

Base1 class

六、类模板案例

类模板允许我们定义通用的类模板,在实例化时可以指定不同的类型、常量和模板参数。

下面是一个使用类模板的示例代码,实现了一个简单的栈(Stack)类模板:

cpp 复制代码
#include <iostream>
#include <vector>

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

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

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

    T top() const {
        if (!elements.empty()) {
            return elements.back();
        }
        throw std::out_of_range("Stack is empty.");
    }

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

int main() {
    Stack<int> stack;
    stack.push(1);
    stack.push(2);
    stack.push(3);

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

    return 0;
}

在这个示例中,Stack 是一个类模板,可以使用不同类型的数据来实例化。在 main() 函数中,我们使用 Stack<int> 来创建一个整数类型的栈,并依次将元素压入栈中,然后通过 top()pop() 函数来访问和删除栈顶元素。

输出结果为

3 2 1

类模板可以实现更加灵活的泛型编程,通过指定模板参数来确定类模板中的具体类型、常量和模板参数。这使得类模板在STL(标准模板库)的容器类(如 vector、list、map 等)中得到了广泛应用。

相关推荐
HC182580858328 分钟前
“倒时差”用英语怎么说?生活英语口语学习柯桥外语培训
学习·生活
学习路上_write12 分钟前
FPGA/Verilog,Quartus环境下if-else语句和case语句RT视图对比/学习记录
单片机·嵌入式硬件·qt·学习·fpga开发·github·硬件工程
非概念18 分钟前
stm32学习笔记----51单片机和stm32单片机的区别
笔记·stm32·单片机·学习·51单片机
林开落L21 分钟前
前缀和算法习题篇(上)
c++·算法·leetcode
Prejudices34 分钟前
C++如何调用Python脚本
开发语言·c++·python
单音GG37 分钟前
推荐一个基于协程的C++(lua)游戏服务器
服务器·c++·游戏·lua
qing_0406031 小时前
C++——多态
开发语言·c++·多态
孙同学_1 小时前
【C++】—掌握STL vector 类:“Vector简介:动态数组的高效应用”
开发语言·c++
charlie1145141911 小时前
Qt Event事件系统小探2
c++·qt·拖放·事件系统
iiiiiankor1 小时前
C/C++内存管理 | new的机制 | 重载自己的operator new
java·c语言·c++