为什么C ++模板不引起多个定义错误?

时间:2018-07-05 02:34:25

标签: c++ templates

当我在C ++文件中包含 protected void ASPxTextBox1_TextChanged(object sender, EventArgs e) { using (SqlConnection cn = new SqlConnection(ConfigurationManager.ConnectionStrings["cn"].ConnectionString)) { if (cn.State == System.Data.ConnectionState.Closed) { cn.Open(); } using (SqlDataAdapter da = new SqlDataAdapter("Select EQPID,RULETYPE,RULENAME,seqNo,SUM(CNT) as CNT,SUM(WFS_QTY) as QTY,(Select SUM(WFS_QTY) from RANK_DECISIVE where EQPtype = 'IASCAN' and DATADATE = '2018/06/12') as TTL_QTY From(Select t1.EQPID, t1.RULETYPE, t1.RULENAME, t1.CNT, t1.WFS_QTY, isNull(t2.rankingIndex, 999) as seqNo from(select a.EQPID, a.RULETYPE, a.RULENAME, a.CNT, a.WFS_QTY, b.ruleName as reportName from RANK_DECISIVE a, station b where a.EQPtype = 'IASCAN' and a.DATADATE = '2018/06/12' and a.EQPID = b.StationName) t1 left join rankingRule t2 on t1.reportName = t2.ReportName and t1.RULETYPE = t2.ruleName and t1.RULENAME = t2.reason) t3 Where EQPID LIKE ('%" + tb1.Text + "%') Group by EQPID, RULETYPE, RULENAME, seqNo ", cn)) { da.Fill(dt); Grid.DataSource = dt; Grid.DataBind(); } } } 并创建<vector>的实例,然后调用std::vector<double>函数时,我的理解是,此时,编译器创建函数的定义并生成必要的代码。但是,我可以从几个不同的C ++文件中调用该函数,这些文件将链接到同一可执行文件中,并且大概每个.cpp文件都会生成一个.o文件,每个文件都是其自己的std::vector<double>::push_back()定义。通常,这种多函数定义会产生链接错误,但是对于模板来说似乎不会发生-为什么会这样?

1 个答案:

答案 0 :(得分:0)

如果链接器看到重新定义,则编译器可以标记要自动删除的某些符号。

在这种情况下,“符号”将是在用具体类型实例化之后,编译器分配给每个模板化函数,模板化成员函数或模板化类的成员函数的唯一名称(错误名称)。在不同的翻译单位(不同的.cpp)中,生成的唯一名称将完全相同。考虑到,除了异常和政治结构之外,在将最终转换应用于汇编代码之前,C ++程序基本上已转换为C程序,因此您的程序起初是一堆函数,其中一些是内联函数,其他是实例化模板化函数,以及其他通常的免费功能。除三分之一外,所有这些都由编译器标记,以使链接器知道重定义可能会出现,并且必须将其静默删除。

如果不同的翻译单元使用以相同类型实例化的相同模板化方法,则整齐的名称也将相同,然后由编译器进行标记。最后,在链接阶段,链接器将看到两个具有相同功能但有标志的重定义。因此,链接器必须删除其中之一,只有一个可以监视清除。

与内联方法相同。

这不会造成任何危害,因为相同类型的相同实例化模板类中的相同方法将产生完全相同的汇编代码,而不管来自哪个翻译单元。

否则,将不可能有内联或模板化方法。

AFAIK,最初的链接器不允许这种标记;它是为使C ++可实现而明确添加的。