在C ++中是否有真正的静态多态性? [英] Is there real static polymorphism in C++?

查看:154
本文介绍了在C ++中是否有真正的静态多态性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是C ++中的一个简单代码:

  #include< iostream& 
#include< typeinfo>

template< typename T>
void function()
{
std :: cout< typeid(T).name()<< std :: endl;
}

int main()
{
function< int>();
function< double>();
return 0;
}



我已经读过C ++中的模板是一个编译时代码特性,这不像C#/ Java中的泛型。



据我所知,C ++编译器会将一个定义的函数分成不同的数字调用计数与不同类型)的函数。



我对不对?我不是C ++编译器的专家,所以我要求你提供一条建议。



如果我对编译器输出的建议是正确的,我想知道如果我可以将上面的代码描述为静态多态性



因为它似乎没有覆盖,而只是从可执行文件调用副本。 ..没有什么应用程序在输出二进制图像,但只有重要的部分是在C + +代码级别,我不知道如何编译器产生输出。

解决方案


在C ++中有真正的静态多边形吗?


绝对有三种静态多态性机制:模板,宏和函数重载。


将把单个定义的函数划分为各种数目(取决于具有不同类型的调用计数)的函数。对不对?


这是一般的想法。被实例化的函数的数量取决于模板参数的排列数量,其可以被明确地指定为 function< int> double> 或 - 对于使用模板参数匹配函数参数的模板,自动从函数参数派生,例如:

  template< typename T,size_t N> 
void f(T(& array)[N])
{}

double d [2]
f(d); // instantiate / uses f< double,2>()

的可执行二进制映像中的每个实例化模板。







我想知道我是否可以将上述代码描述为静态多态性? p>

不是真的。




  • 模板<>函数实例化两种类型




    • 至关重要的是,多态是 / em>

    • 用于选择函数的两个实例中的哪一个在调用站点分派


      <在这样的实例化期间,对 int typeid(T) >



  • 简单来说,静态和名义动态(但这里可能是静态的)多态的混合支持您使用 std :: cout




  • 背景 - 多态性和代码生成



    我认为对于多态性至关重要的要求是:




    • 编译器(无论是正常代码还是每个模板实例化或宏替换),编译器会自动选择(如果需要创建) - 内联或调用 - 不同类型适当的行为(机器代码)




      • ie编译器仅基于所涉及的变量的类型来进行代码选择/创建,而不是由程序员在不同的函数名称/实例化之间的选择进行显式硬编码,每个函数名称/实例化仅仅能够处理一种类型或排列


      • ,例如 std :: cout<因为 x 的类型不同,但仍然输出 x 的值,而非多态性 printf(%d,x)处理 int 手动修改为 printf(%c,x); 如果 x char




    $ b 我们试图用多态性实现的是更一般的:




    • 对于没有嵌入显式类型检测和分支代码的多种类型的数据




      • 源代码包含 if(type == X)f1(x)else f2(x); -style code

      li>
    • 减少维护负担 明确更改变量的类型更少的后续更改需要在源代码中手动进行




    这些大图片方面在C ++中支持如下:



    < 相同源代码 实例化 >
    类型的 不同行为 (机器代码) 多态性),




    • 实际上称为实例化模板和替换用于预处理器宏,但为方便起见,我将在后面使用实例化;概念上,重新编译或重新解释...


  • )的 (静态或动态)正在处理的数据正在处理中。


  • http://stackoverflow.com/questions/5854581/polymorphism-in-c\"> c ++中的多态性



    不同类型的多态性涉及一种或两种

    的情况下可能会发生这种情况:

    (1)模板和预处理器


  • 1)通常在调度期间(2)模板(没有匹配的完全专业化)和功能类似宏不会递归展开)

  • 实例化(1)当编译器选择预先存在的函数重载模板专用化 >


    $ b
    $ b

    函数< int> 函数< double> c> function 模板代码为每种类型创建不同的代码,以便获得实例化(1)如上。但是,你是硬编码哪个实例化调用,而不是让编译器隐式选择一个实例化基于某些参数的类型,即所以你不直接使用隐式调度ala(2),当调用 function 。事实上, function 缺少编译器可以用于隐式选择模板实例化的参数。



    实例化)单独是 足以考虑您的代码已使用多态性。



    那么,什么是明确的多态性?

    h2>

    为了说明模板如何支持dispatch(2)以及实例化(1)和不可置信地提供多态性,请考虑:

     模板< typename T> 
    void function(T t)
    {
    std :: cout< typeid(T).name()<< std :: endl;
    }

    function(4); // note:int argument,use function< int>(...)
    function(12.3); // note:double argument,use function< double>(...)

    利用 implicit dispatch to type-appropriate code - aspect2.





    非类型参数



    ,C ++提供了使用诸如boolean, int 等整型参数来实例化模板的能力,并且可以在不改变数据类型的情况下将它们用于所有类型的事物,任何多态性。宏更灵活。






    请注意,在C.R.T.P.中使用模板。样式是 静态多态的要求 - 这是一个示例应用程序。在实例化期间,当将参数指定类型中的实现匹配操作时,编译器展现静态多态性。






    / h2>

    获取多态性的确定性定义很困难。维基百科引用Bjarne Stroustrup的在线词汇表为不同类型的实体提供单一接口:这意味着 struct X {void f(); }; struct Y {void f(); }; 已经表示多态性,但是当我们使用客户端代码的接口对应时,我们只得到多态性。 template< typename T> void poly(T& t){t.f(); } 需要对每个实例化的 t.f()进行静态多态分派。


    Here is a simple code in C++:

    #include <iostream>
    #include <typeinfo>
    
    template<typename T>
    void function()
    {
       std::cout << typeid(T).name() << std::endl;
    }
    
    int main()
    {
       function<int>();
       function<double>();
       return 0;
    }
    

    I have read that templates in C++ is a compile-time feature, which is not like generics in C#/Java.

    So as I understood, the C++ compiler will divide a single defined function into various number (depends on calls count with different type) of functions.

    Am I right or not? I'm not an expert in C++ compilers, so I'm asking a piece of advice from you.

    If my suggestion about compiler output is correct, I want to know if I can describe the code above as static polymorphism?

    Because it seems to be not overriding, but just calling a copy from executable or... it doesn't matter what does application have in output binary image, but only the important part is in C++ code level and I musn't look at how does compiler produce an output.

    解决方案

    Is there real static polymorhism in C++?

    Absolutely - there are three mechanisms for static polymorphism: templates, macros and function overloading.

    So as I understood, the C++ compiler will divide a single defined function into various number (depends on calls count with different type) of functions. Am I right or not?

    That's the general idea. The number of functions that get instantiated depends on the number of permutations of template parameters, which may be explicitly specified as in function<int> and function<double> or - for templates that use the template parameters to match function arguments - automatically derived from the function arguments, for example:

    template <typename T, size_t N>
    void f(T (&array)[N])
    { }
    
    double d[2];
    f(d);   // instantiates/uses f<double, 2>()
    

    You should end up with a single copy of each instantiated template in the executable binary image.


    I want to know if I can describe the code above as static polymorphism?

    Not really.

    • template<> function is instantiated for two types

      • crucially, polymorphism is not used to choose which of the two instantiations of function to dispatch to at the call sites

      • trivially, during such instantiations typeid(T) is evaluated for int and double and effectively behaves polymorphically from a programmer perspective (it's a compiler keyword though - implementation unknown)

    • trivially, a mix of static and nominally dynamic (but here likely optimisable to static) polymorphism supports your use of std::cout

    Background - polymorphism and code generation

    The requirement I consider crucial for polymorphism is:

    • when code is compiled (be it "normal" code or per template instantiation or macro substitution), the compiler automatically chooses (creates if necessary) - and either inlines or calls - distinct type-appropriate behaviour (machine code)

      • i.e. code selection/creation is done by the compiler based only on the type(s) of variable(s) involved, rather than being explicitly hard-coded by the programmer's choice between distinct function names / instantiations each only capable of handling one type or permutation of types

      • for example, std::cout << x; polymorphically invokes different code as the type of x is varied but still outputs x's value, whereas the non-polymorphic printf("%d", x) handles ints but needs to be manually modified to printf("%c", x); if x becomes a char.

    But, what we're trying to achieve with polymorphism is a bit more general:

    • reuse of algorithmic code for multiple types of data without embedding explicit type-detection and branching code

      • that is, without the program source code containing if (type == X) f1(x) else f2(x);-style code
    • reduced maintenance burden as after explicitly changing a variable's type fewer consequent changes need to be manually made throughout the source code

    These bigger-picture aspects are supported in C++ as follows:

    1. instantiation of the same source code to generate distinct behaviours (machine code) for some other type or permutation of types (this is an aspect of parametric polymorphism),

      • actually known as "instantiation" for templates and "substitution" for preprocessor macros, but I'll use "instantiation" hereafter for convenience; conceptually, re-compilation or re-interpretation...
    2. implicit dispatch (static or dynamic) to distinct behaviour (machine code) appropriate to the distinct type(s) of data being processed.

    ...and in some minor ways per my answer at Polymorphism in c++

    Different types of polymorphism involve either or both of these:

    • dispatch (2) can happen during instantiation (1) for templates and preprocessor macros,

    • instantiation (1) normally happens during dispatch (2) for templates (with no matching full specialisation) and function-like macros (kind of cyclic, though macros don't expand recursively)

    • dispatch (2) can be happen without instantiation (1) when the compiler selects a pre-existing function overload or template specialisation, or when the compiler triggers virtual/dynamic dispatch.

    What does your code actually use?

    function<int> and function<double> reuse the function template code to create distinct code for each of those types, so you are getting instantiation (1) as above. But, you are hard-coding which instantiation to call rather than having the compiler implicitly select an instantiation based on the type of some parameter, i.e. so you don't directly utilise implicit dispatch ala (2) when calling function. Indeed, function lacks a parameter that the compiler could use for implicit selection of a template instantiation.

    Instantiation (1) alone is not enough to consider your code to have used polymorphism. Still, you've achieved convenient code re-use.

    So what would be unambiguously polymorphic?

    To illustrate how templates can support dispatch (2) as well as instantiation (1) and unarguably provide "polymorphism", consider:

    template<typename T>
    void function(T t)
    {
        std::cout << typeid(T).name() << std::endl;
    }
    
    function(4);      // note: int argument, use function<int>(...)
    function(12.3);   // note: double argument, use function<double>(...)
    

    The above code also utilises the implicit dispatch to type-appropriate code - aspect "2." above - of polymorphism.


    Non type parameters

    Interestingly, C++ provides the ability to instantiate templates with integral parameters such as boolean, int and pointer constants, and use them for all manner of things without varying your data types, and therefore without any polymorphism involved. Macros are even more flexible.


    Note that using a template in a C.R.T.P. style is NOT a requirement for static polymorphism - it's an example application thereof. During instantiation, the compiler exhibits static polymorphism when matching operations to implementations in the parameter-specified type.


    Discussion on terminology

    Getting a definitive definition of polymorphism is difficult. wikipedia quotes Bjarne Stroustrup's online Glossary "providing a single interface to entities of different types": this implies struct X { void f(); }; struct Y { void f(); }; already manifests polymorphism, but IMHO we only get polymorphism when we use the correspondence of interface from client code, e.g. template <typename T> void poly(T& t) { t.f(); } requires static polymorphic dispatch to t.f() for each instantiation.

    这篇关于在C ++中是否有真正的静态多态性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆