• C++模板——待决名


    C++模板——待决名

    本文将持续更新,如果有了解这块内容的小伙伴欢迎评论区留言,最近遇到这个问题很多次了😭

    概念

    参考官方文档:

    简单来说:

    template<typename T>
    struct X {
        void f_x(){}
    };
    template<typename T>
    struct Y : X<T> {
        void f_y() {
            f_x(); // 非待决名,函数查找在不知道T的具体类型时(即模板未实例化)就查找【立即绑定】
            this->f_x(); // 待决名,函数查找在知道T的具体类型时(即模板已实例化)才查找【待会绑定】
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    我们应该在待决名的情况下,使用待决名的成员;在非待决名的情况下,使用非待决名的成员。

    在模板中的使用

    参考官方文档:无限定的名字查找 - cppreference.com

    问题

    问题1:

    #include 
    
    template<typename T = int>
    class Base {
    public:
        Base() :m_a(0) {}
        Base(T a) :m_a(a) {}
        virtual void func(){
            // 假设T类型重载了<<运算符且能被输出
            std::cout << "Base func()" << m_a << std::endl;
        }
    protected:
        T m_a;
    };
    
    template<typename T = int>
    class Derived :public Base<T> {
    public:
        Derived() : Base<T>() {}
        Derived(T a, T b) :Base<T>(a), m_b(b) {}
        void func() override {
            // 假设T类型重载了<<运算符且能被输出
            std::cout << "Derived func()" << m_a << " " << m_b << std::endl; // m_a是非待决名
        }
    private:
        T m_b;
    };
    
    int main() {
        Derived o(2.3, 1.4);
        o.func();
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    上述代码中,这句std::cout << "Derived func()" << m_a << " " << m_b << std::endl;报错:m_a未声明的标识符

    解决方案

    • 法1,让成员成为待决名的:将使用m_a改为this->m_a,或使用显式指定m_a命名空间为Base::m_a
    • 法2,保留成员为非待决名不动,让模板类实例化:在继承模板类时将模板类实例化为特定的类型,比如Base,就不会报错了

    问题2:

    // 邻接矩阵
    template <typename T = char>
    struct MGraph {
        T vex[MAX_VERTEX_NUM];                     // 顶点表(用来存放顶点的信息)
        int edge[MAX_VERTEX_NUM][MAX_VERTEX_NUM];  // 邻接矩阵(用来存放边和边权)
        int vex_num, arc_num;                      // 当前的顶点数和弧数
    };
    
    // 邻接表
    struct ArcNode {  // 边表结点
        int adjvex;   // 出边终点在顶点表中的下标
        ArcNode* next;
    };
    template <typename T = char>
    struct VNode {  // 顶点表结点
        T data;
        ArcNode* first;
    };
    template <typename T = char>
    struct ALGraph {                    // 邻接表类型
        VNode<T> node[MAX_VERTEX_NUM];  // 顶点表,其中的每个顶点都连着一个出边表
        int vex_num, arc_num;           // 当前的顶点数和弧数
    };
    
    // 将邻接表转为邻接矩阵
    template <typename T = char>
    void convertToMatrix(ALGraph<T>& g, MGraph<T>& m) {
        for (int i = 0; i < g.vex_num; i++) {
            auto p = g.node[i].first;  // first是非待决名。不过这里编译能通过,只不过这里写auto的话用不了代码提示了
            while (p != nullptr) {
                m.edge[i][p->adjvex] = 1;
                p = p->next;
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    解决方案

    • 法1,让first成为待决名的,即用typename关键字显式指定p的类型:typename Graph::ArcNode* p = g.node[i].first;
    • 法2,保留成员为非待决名不动,让模板函数实例化
  • 相关阅读:
    【Hadoop】Apache Hadoop YARN
    Debezium系列之:IDEA集成词法和语法分析ANTLR,查看debezium支持的ddl、dml等语句
    [Typescript]基础篇之 String 对象
    视频特效编辑软件 After Effects 2022 mac中文版介绍 (ae 2022)
    音频编辑软件Steinberg SpectraLayers Pro mac中文软件介绍
    localStorage容量太小? 试试它们
    java计算机毕业设计ssm汽车租赁管理系统n5s69(附源码、数据库)
    基于python的语音识别与蓝牙通信的温控系统毕设项目
    《福格行为模型》笔记 --- ta为什么总是想得多做得少
    usb与 hid, 串口 趣谈
  • 原文地址:https://blog.csdn.net/m0_58699417/article/details/133705868