C++ 中的多态性
AFAIK:
C++ 提供了三种不同类型的多态性。
- 虚函数
- 函数名重载
- 运算符重载
除了上述三种类型的多态性之外,还存在其他类型的多态性:
- 运行时
- 编译时临时多态性
- 参数多态性
- 我
知道运行时多态性可以是通过虚拟函数实现 和静态多态性可以通过模板函数来实现,
但是对于另外两种
- 即席多态性
- ,参数多态性 网站说,
广告-临时多态性:
如果可以使用的实际类型的范围是有限的,并且在使用之前必须单独指定组合,则称为临时多态性。
参数多态性:
如果所有代码都是在不提及任何特定类型的情况下编写的,因此可以透明地与任意数量的新类型一起使用,则称为参数多态性。
我几乎无法理解它们:(
如果可能的话,谁能用一个例子来解释它们呢? 我希望这个问题的答案能够对许多刚从大学毕业的学生有所帮助。
AFAIK:
C++ provides three different types of polymorphism.
- Virtual functions
- Function name overloading
- Operator overloading
In addition to the above three types of polymorphism, there exist other kinds of polymorphism:
- run-time
- compile-time
- ad-hoc polymorphism
- parametric polymorphism
I know that runtime polymorphism can be achieved by virtual functions
and static polymorphism can be achieved by template functions
But for the other two
- ad-hoc polymorphism
- parametric polymorphism
the website says,
ad-hoc polymorphism:
If the range of actual types that can be used is finite and the combinations must be individually specified prior to use, this is called ad-hoc polymorphism.
parametric polymorphism:
If all code is written without mention of any specific type and thus can be used transparently with any number of new types it is called parametric polymorphism.
I can hardly understand them :(
can anyone explain them both if possible with an example?
I hope the answers to this questions would be helpful for many new passouts from their colleges.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
多态性的理解/要求
要理解多态性(计算科学中使用的术语),从简单的测试和定义开始会有所帮助。考虑:
这里,
f()
用于执行某些操作,并被赋予值x
和y
作为输入。C++ 多态性机制
显式程序员指定的多态性
您可以编写
f()
,使其可以通过以下任意方式对多种类型进行操作:预处理:
重载:
模板:
虚拟调度:
其他相关机制
编译器为内置类型提供的多态性、标准转换和强制转换/强制转换将在稍后讨论以保证完整性:
术语
进一步分类
考虑到上面的多态机制,我们可以通过多种方式对它们进行分类:
什么时候选择多态类型特定的代码?
int
参数调用f
- 根据所使用的多态机制和内联选择,编译器可能会避免为生成任何代码f(double)
,或者生成的代码可能在编译或链接的某个时刻被丢弃。 (除虚拟调度之外的所有机制)支持哪些类型?
参数化意味着您可以尝试将该函数用于各种参数类型,而无需专门执行任何操作来启用其对它们的支持(例如模板、宏)。具有类似于模板/宏所期望的函数/运算符的对象1是模板/宏完成其工作所需的全部内容,具体类型无关紧要。 C++20 引入的“概念”表达并强制执行此类期望 - 请参阅 cppreference 页面位于此处。
参数多态性提供了鸭子类型 - 这一概念源自 James Whitcomb Riley,他显然说过“当我看到一只像鸭子一样行走、像鸭子一样游泳并嘎嘎叫的鸟时就像鸭子一样,我称那只鸟为鸭子。”.
子类型(又名包含)多态性允许您在不更新算法/函数的情况下处理新类型,但它们必须派生自相同的基类(虚拟调度)
1 - 模板是极其灵活。 SFINAE(另请参阅
std::enable_if
) 有效地允许对参数多态性的多组期望。例如,您可以编码,当您正在处理的数据类型具有.size()
成员时,您将使用一个函数,否则使用另一个不需要.size 的函数()
(但可能会以某种方式受到影响 - 例如使用较慢的strlen()
或不在日志中打印有用的消息)。您还可以在使用特定参数实例化模板时指定临时行为,或者保留一些参数参数化 (部分模板专业化)或不(< em>完全专业化)。“多态”
Alf Steinbach 评论说,在 C++ 标准中,多态仅指使用虚拟分派的运行时多态。通用比较科学。根据 C++ 创建者 Bjarne Stroustrup 的术语表(http://www.stroustrup.com/glossary),含义更具包容性。 html):
这个答案 - 就像问题一样 - 将 C++ 功能与 Comp 相关联。科学。术语。
与 C++ 标准的讨论
使用比 Comp 更窄的“多态性”定义。科学。社区,为了确保您受众的相互理解,请考虑...
尽管如此,对于成为一名出色的 C++ 程序员来说,最重要的是理解多态性真正为您带来什么......
让您编写一次“算法”代码,然后应用它适用于多种类型的数据
...然后要非常了解不同的多态机制如何满足您的实际需求。
运行时多态性适合:
当运行时多态性没有明确的驱动程序时,编译时选项通常更可取。考虑一下:
__FILE__
、__LINE__
、字符串文字连接和宏的其他独特功能(仍然是邪恶的;-))支持多态性的其他机制
正如所承诺的,为了完整性,涵盖了几个外围主题:
这个答案总结讨论如何结合上述内容来增强和简化多态代码 - 特别是参数多态性(模板和宏)。
映射到特定类型操作的机制
>编译器提供的隐式重载
从概念上讲,编译器重载了内置类型的许多运算符。它在概念上与用户指定的重载没有什么不同,但被列出是因为它很容易被忽视。例如,您可以使用相同的符号
x += 2
添加到int
和double
中,编译器会生成:然后,重载无缝扩展到用户定义的类型:
编译器为基本类型提供的重载在高级 (3GL+) 计算机语言中很常见,并且对多态性的显式讨论通常意味着更多内容。 (2GL - 汇编语言 - 通常要求程序员为不同类型显式使用不同的助记符。
)标准转换
C++ 标准的第四部分描述了标准转换。
第一点总结得很好(来自旧草案 - 希望仍然基本正确):
以下集合中的零个或一个转换:左值到右值转换、数组到指针转换以及函数到指针转换。
来自以下集合的零次或一次转换:整型提升、浮点提升、整型转换、浮点转换、浮点整型转换、指针转换、指向成员的指针转换和布尔转换。
零或一次资格转换。
这些转换允许诸如以下的代码:
应用先前的测试:
a()
本身专门为double
运行代码,因此不是多态的。但是,在第二次调用
a()
时,编译器知道为“浮点提升”(标准§4)生成类型适当的代码,以将42
转换为 <代码>42.0。该额外代码位于调用函数中。我们将在结论中讨论这一点的重要性。>强制、强制转换、隐式构造函数
这些机制允许用户定义的类指定类似于内置类型的标准转换的行为。让我们看一下:
这里,对象
std::cin
在转换运算符的帮助下在布尔上下文中进行计算。从概念上讲,这可以与上述主题中的标准转换中的“整体促销”等分组。隐式构造函数实际上做同样的事情,但由强制转换类型控制:
编译器提供的重载、转换和强制的含义
考虑:
如果我们希望将数量
x
视为实数在除法期间(即为 6.5,而不是向下舍入为 6),我们仅需要更改为typedef double Amount
。这很好,但是让代码显式地“类型正确”并不需要太多工作:
但是,考虑一下我们可以将第一个版本转换为模板:
正是由于这些小小的“便利功能”,它可以很容易地实例化为
int
或double
并按预期工作。如果没有这些功能,我们需要显式转换、类型特征和/或策略类,以及一些冗长、容易出错的混乱,例如:编译器为内置类型提供的运算符重载、标准转换、转换/强制/隐式构造函数 - 它们所有这些都为多态性提供了微妙的支持。根据此答案顶部的定义,它们通过映射来解决“查找并执行适合类型的代码”:
“远离”参数类型
来自多态算法代码处理的多种数据类型
为为(可能更少)数量(相同或其他)类型编写的代码。
从常量类型的值“到”参数类型
它们本身不会建立多态上下文,但确实有助于增强/简化代码在这样的背景下。
你可能会觉得被骗了……这似乎并不多。重要的是,在参数多态上下文中(即在模板或宏内部),我们试图支持任意大范围的类型,但通常希望用其他函数、文字和为设计目的而设计的操作来表达对它们的操作。一小组类型。当操作/值在逻辑上相同时,它减少了在每种类型的基础上创建几乎相同的函数或数据的需要。这些功能相互配合,增加了一种“尽力而为”的态度,通过使用有限的可用功能和数据来执行直观预期的操作,并且仅在存在真正模糊性时才停止并出现错误。
这有助于限制对支持多态代码的多态代码的需求,围绕多态性的使用绘制更紧密的网络,因此本地化使用不会强制广泛使用,并根据需要提供多态性的好处,而无需在编译时,在目标代码中拥有同一逻辑函数的多个副本以支持所使用的类型,并进行虚拟调度,而不是内联或至少是编译时解析的调用。正如 C++ 中的典型情况一样,程序员有很大的自由来控制多态性的使用范围。
Understanding of / requirements for polymorphism
To understand polymorphism - as the term is used in Computing Science - it helps to start from a simple test for and definition of it. Consider:
Here,
f()
is to perform some operation and is being given valuesx
andy
as inputs.C++ mechanisms for polymorphism
Explicit programmer-specified polymorphism
You can write
f()
such that it can operate on multiple types in any of the following ways:Preprocessing:
Overloading:
Templates:
Virtual dispatch:
Other related mechanisms
Compiler-provided polymorphism for builtin types, Standard conversions, and casting/coercion are discussed later for completeness as:
Terminology
Further categorisation
Given the polymorphic mechanisms above, we can categorise them in various ways:
When is the polymorphic type-specific code selected?
f
above withint
arguments - depending on the polymorphic mechanism used and inlining choices the compiler might avoid generating any code forf(double)
, or generated code might be thrown away at some point in compilation or linking. (all mechanisms above except virtual dispatch)Which types are supported?
Parametric meaning you can just try to use the function for various parameter types without specifically doing anything to enable its support for them (e.g. templates, macros). An object with functions/operators that act like the template/macro expects1 is all that template/macro needs to do its job, with the exact type being irrelevant. The "concepts" introduced by C++20 express and enforce such expectations - see cppreference page here.
Parametric polymorphism provides duck typing - a concept attributed to James Whitcomb Riley who apparently said "When I see a bird that walks like a duck and swims like a duck and quacks like a duck, I call that bird a duck.".
Subtype (aka inclusion) polymorphism allows you to work on new types without updating the algorithm/function, but they must be derived from the same base class (virtual dispatch)
1 - Templates are extremely flexible. SFINAE (see also
std::enable_if
) effectively allows several sets of expectations for parametric polymorphism. For example, you might encode that when the type of data you're processing has a.size()
member you'll use one function, otherwise another function that doesn't need.size()
(but presumably suffers in some way - e.g. using the slowerstrlen()
or not printing as useful a message in the log). You can also specify ad-hoc behaviours when the template is instantiated with specific parameters, either leaving some parameters parametric (partial template specialisation) or not (full specialisation)."Polymorphic"
Alf Steinbach comments that in the C++ Standard polymorphic only refers to run-time polymorphism using virtual dispatch. General Comp. Sci. meaning is more inclusive, as per C++ creator Bjarne Stroustrup's glossary (http://www.stroustrup.com/glossary.html):
This answer - like the question - relates C++ features to the Comp. Sci. terminology.
Discussion
With the C++ Standard using a narrower definition of "polymorphism" than the Comp. Sci. community, to ensure mutual understanding for your audience consider...
Still, what's crucial to being a great C++ programmer is understanding what polymorphism's really doing for you...
letting you write "algorithmic" code once and then apply it to many types of data
...and then be very aware of how different polymorphic mechanisms match your actual needs.
Run-time polymorphism suits:
Base*
s,When there's not a clear driver for run-time polymorphism, compile-time options are often preferable. Consider:
__FILE__
,__LINE__
, string literal concatenation and other unique capabilities of macros (which remain evil ;-))Other mechanisms supporting polymorphism
As promised, for completeness several peripheral topics are covered:
This answer concludes with a discussion of how the above combine to empower and simplify polymorphic code - especially parametric polymorphism (templates and macros).
Mechanisms for mapping to type-specific operations
> Implicit compiler-provided overloads
Conceptually, the compiler overloads many operators for builtin types. It's not conceptually different from user-specified overloading, but is listed as it's easily overlooked. For example, you can add to
int
s anddouble
s using the same notationx += 2
and the compiler produces:Overloading then seamlessly extends to user-defined types:
Compiler-provided overloads for basic types is common in high-level (3GL+) computer languages, and explicit discussion of polymorphism generally implies something more. (2GLs - assembly languages - often require the programmer to explicitly use different mnemonics for different types.)
> Standard conversions
The C++ Standard's fourth section describes Standard conversions.
The first point summarises nicely (from an old draft - hopefully still substantially correct):
Zero or one conversion from the following set: lvalue-to-rvalue conversion, array-to-pointer conversion, and function-to-pointer conversion.
Zero or one conversion from the following set: integral promotions, floating point promotion, integral conversions, floating point conversions, floating-integral conversions, pointer conversions, pointer to member conversions, and boolean conversions.
Zero or one qualification conversion.
These conversions allow code such as:
Applying the earlier test:
a()
itself runs code specifically fordouble
and is therefore not polymorphic.But, in the second call to
a()
the compiler knows to generate type-appropriate code for a "floating point promotion" (Standard §4) to convert42
to42.0
. That extra code is in the calling function. We'll discuss the significance of this in the conclusion.> Coercion, casts, implicit constructors
These mechanisms allow user-defined classes to specify behaviours akin to builtin types' Standard conversions. Let's have a look:
Here, the object
std::cin
is evaluated in a boolean context, with the help of a conversion operator. This can be conceptually grouped with "integral promotions" et al from the Standard conversions in the topic above.Implicit constructors effectively do the same thing, but are controlled by the cast-to type:
Implications of compiler-provided overloads, conversions and coercion
Consider:
If we want the amount
x
to be treated as a real number during the division (i.e. be 6.5 rather than rounded down to 6), we only need change totypedef double Amount
.That's nice, but it wouldn't have been too much work to make the code explicitly "type correct":
But, consider that we can transform the first version into a
template
:It's due to those little "convenience features" that it can be so easily instantiated for either
int
ordouble
and work as intended. Without these features, we'd need explicit casts, type traits and/or policy classes, some verbose, error-prone mess like:So, compiler-provided operator overloading for builtin types, Standard conversions, casting / coercion / implicit constructors - they all contribute subtle support for polymorphism. From the definition at the top of this answer, they address "finding and executing type-appropriate code" by mapping:
"away" from parameter types
from the many data types polymorphic algorithmic code handles
to code written for a (potentially lesser) number of (the same or other) types.
"to" parametric types from values of constant type
They do not establish polymorphic contexts by themselves, but do help empower/simplify code inside such contexts.
You may feel cheated... it doesn't seem like much. The significance is that in parametric polymorphic contexts (i.e. inside templates or macros), we're trying to support an arbitrarily large range of types but often want to express operations on them in terms of other functions, literals and operations that were designed for a small set of types. It reduces the need to create near-identical functions or data on a per-type basis when the operation/value is logically the same. These features cooperate to add an attitude of "best effort", doing what's intuitively expected by using the limited available functions and data and only stopping with an error when there's real ambiguity.
This helps limit the need for polymorphic code supporting polymorphic code, drawing a tighter net around the use of polymorphism so localised use doesn't force widespread use, and making the benefits of polymorphism available as needed without imposing the costs of having to expose implementation at compile time, have multiple copies of the same logical function in the object code to support the used types, and in doing virtual dispatch as opposed to inlining or at least compile-time resolved calls. As is typical in C++, the programmer is given a lot of freedom to control the boundaries within which polymorphism is used.
在 C++ 中,重要的区别是运行时绑定与编译时绑定。正如我稍后将解释的,临时与参数并没有真正的帮助。
注意 - 运行时多态性仍可能在编译时得到解决,但这只是优化。需要有效地支持运行时解析,并权衡其他问题,是导致虚拟函数成为现实的部分原因。这对于 C++ 中所有形式的多态性来说都是非常关键的——每一种多态性都源于在不同上下文中进行的不同的权衡。
函数重载和运算符重载在各个方面都是相同的。使用它们的名称和语法不会影响多态性。
模板允许您一次指定大量函数重载。
对于相同的解析时间想法,还有另一组名称...
这些名称与 OOP 更相关,因此说模板或其他非成员函数使用早期绑定有点奇怪。
为了更好地理解虚函数和函数重载之间的关系,了解“单次调度”和“多次调度”之间的区别也很有用。这个想法可以理解为一个渐进......
显然,OOP 不仅仅是一个将某个参数指定为特殊参数的借口,但这只是其中的一部分。回到我所说的权衡——单次调度很容易有效地完成(通常的实现称为“虚拟表”)。多重分派比较尴尬,不仅是效率方面,而且对于单独编译来说也是如此。如果你好奇,你可以查找“表达问题”。
正如对非成员函数使用术语“早期绑定”有点奇怪一样,使用在编译时解决多态性的术语“单分派”和“多重分派”也有点奇怪。通常,C++ 被认为没有多重分派,这被认为是一种特定类型的运行时解析。然而,函数重载可以看作是在编译时完成的多次调度。
回到参数多态性与临时多态性,这些术语在函数式编程中更流行,但在 C++ 中不太适用。即便如此...
参数多态性意味着您将类型作为参数,并且无论您为这些参数使用什么类型,都将使用完全相同的代码。
临时多态性是临时的,因为您根据特定类型提供不同的代码。
重载和虚函数都是临时多态性的例子。
再说一遍,有一些同义词...
不过这些并不完全是同义词,尽管它们通常被视为同义词,而这就是 C++ 中可能出现混淆的地方。
将它们视为同义词背后的原因是,通过将多态性限制到特定的类型类别,可以使用特定于这些类型类别的操作。这里的“类”一词可以在 OOP 意义上解释,但实际上只是指(通常命名的)共享某些操作的类型集。
因此,参数多态性通常被认为(至少默认情况下)意味着不受约束的多态性。由于无论类型参数如何,都使用相同的代码,因此唯一支持的操作是适用于所有类型的操作。通过不限制类型集,您可以严格限制可应用于这些类型的操作集。
例如,在 Haskell 中,您可以拥有...
这里的
a
是不受约束的多态类型。它可以是任何东西,所以我们对这种类型的值无能为力。这里,
a
被限制为Num
类的成员 - 行为类似于数字的类型。该约束允许您使用这些值执行数字操作,例如将它们相加。甚至3
也是多态的 - 类型推断表明您指的是a
类型的3
。我认为这是受约束的参数多态性。只有一种实现,但它只能应用于有限的情况。特别的方面是选择使用哪个
+
和3
。Num
的每个“实例”都有其自己独特的实现。所以即使在 Haskell 中,“参数”和“无约束”也不是真正的同义词 - 不要责怪我,这不是我的错!在 C++ 中,重载和虚函数都是临时多态性。即席多态性的定义并不关心实现是在运行时还是编译时选择的。
如果每个模板参数都有类型
typename
,C++ 就非常接近模板的参数多态性。有类型参数,并且无论使用哪种类型都有一个实现。然而,“替换失败不是错误”规则意味着隐式约束是由于在模板中使用操作而出现的。其他复杂性包括用于提供替代模板的模板专业化 - 不同的(临时)实现。因此,在某种程度上,C++ 具有参数多态性,但它受到隐式约束,并且可能被临时替代方案覆盖 - 即,这种分类实际上不适用于 C++。
In C++, the important distinction is run-time vs. compile-time binding. Ad-hoc vs. parametric doesn't really help, as I'll explain later.
Note - run-time polymorphism may still be resolved at compile-time, but that's just optimization. Needing to support run-time resolution efficiently, and trading off against other issues, is part of what led to virtual functions being what they are. And that's really key for all forms of polymorphism in C++ - each arises from different sets of trade-offs made in a different context.
Function overloading and operator overloading are the same thing in every way that matters. The names and the syntax for using them doesn't affect polymorphism.
Templates allow you to specify lots of function overloads at once.
There's another set of names for the same resolution-time idea...
These names are more associated with OOP, so it's a bit odd to say that a template or other non-member function uses early binding.
To better understand the relationship between virtual functions and function overloading, it's also useful to understand the difference between "single dispatch" and "multiple dispatch". The idea can be understood as a progression...
There's obviously more to OOP than an excuse to nominate one parameter as special, but that is one part of it. And relating back to what I said about trade-offs - single dispatch is quite easy to do efficiently (the usual implementation is called "virtual tables"). Multiple dispatch is more awkward, not just in terms of efficiency, but also for separate compilation. If you're curious, you might look up "the expression problem".
Just as it's a bit odd to use the term "early binding" for non-member functions, it's a bit odd to use the terms "single dispatch" and "multiple dispatch" where polymorphism is resolved at compile-time. Usually, C++ is considered not to have multiple dispatch, which is considered a particular kind of run-time resolution. However, function overloading can be seen as multiple-dispatch done at compile-time.
Getting back to parametric vs. ad-hoc polymorphism, these terms are more popular in functional programming, and they don't quite work in C++. Even so...
Parametric polymorphism means that you have types as parameters, and the exact same code is used irrespective of what type you use for those parameters.
Ad-hoc polymorphism is ad-hoc in the sense that you provide different code depending on the particular types.
Overloading and virtual functions are both examples of ad-hoc polymorphism.
Again, there's some synonyms...
Except these aren't quite synonyms, though they're commonly treated as though they were, and that's where confusion is likely to arise in C++.
The reasoning behind treating these as synonyms is that by constraining polymorphism to particular classes of types, it becomes possible to use operations specific to those classes of types. The word "classes" here can be interpreted in the OOP sense, but really just refers to (usually named) sets of types that share certain operations.
So parametric polymorphism is usually taken (at least by default) to imply unconstrained polymorphism. Because the same code is used irrespective of the type parameters, the only supportable operations are those that work for all types. By leaving the set of types unconstrained, you severely limit the set of operations you can apply to those types.
In e.g. Haskell, you can have...
The
a
here is an unconstrained polymorphic type. It could be anything, so there's not much we can do with values of that type.Here,
a
is constrained to be a member of theNum
class - types that act like numbers. That constraint allows you to do number-ish things with those values, such as add them. Even the3
is polymorphic - type inference figures out that you mean the3
of typea
.I think of this as constrained parametric polymorphism. There's only one implementation, but it can only be applied in constrained cases. The ad-hoc aspect is the choice of which
+
and3
to use. Each "instance" ofNum
has it's own distinct implementation of these. So even in Haskell "parametric" and "unconstrained" aren't really synonyms - don't blame me, it's not my fault!In C++, both overloading and virtual functions are ad-hoc polymorphism. The definition of ad-hoc polymorphism doesn't care whether the implementation is selected at run-time or compile-time.
C++ gets very close to parametric polymorphism with templates if every template parameter has type
typename
. There are type parameters, and there's a single implementation no matter which types are used. However, the "Substitution Failure Is Not An Error" rule means that implicit constraints arise as a result of using operations within the template. Additional complications include template specialization for providing alternative templates - different (ad-hoc) implementations.So in a way C++ has parametric polymorphism, but it's implicitly constrained and could be overridden by ad-hoc alternatives - ie this classification doesn't really work for C++.
对于ad-hoc多态性,它意味着函数重载或运算符重载。在这里查看:
http://en.wikipedia.org/wiki/Ad-hoc_polymorphism
至于参数多态性,模板函数也可以计算在内,因为它们不一定接受 FIXED 类型的参数。例如,一个函数可以对整数数组进行排序,也可以对字符串数组进行排序等。
http:// en.wikipedia.org/wiki/Parametric_polymorphism
As to ad-hoc polymorphism, it means function overloading or operator overloading. Check out here:
http://en.wikipedia.org/wiki/Ad-hoc_polymorphism
As to parametric polymorphism, template functions can also be counted in because they don't necessarily take in parameters of FIXED types. For example, one function can sort array of integers and it can also sort array of strings, etc.
http://en.wikipedia.org/wiki/Parametric_polymorphism
这可能没有任何帮助,但我这样做是为了向我的朋友介绍编程,通过给出定义的函数,例如主函数的
START
和END
,所以它是并不太令人畏惧(他们只使用了 main.cpp 文件)。它包含多态类和结构、模板、向量、数组、预处理器指令、友谊、运算符和指针(在尝试多态性之前您可能应该了解所有这些):注意:它尚未完成,但您可以了解想法
main.cpp
main.h
This may not be of any help, but I made this to introduce my friends to programming by giving out defined functions, like
START
, andEND
for the main function so it was not too daunting (they only used the main.cpp file). It contains Polymorphic classes and structs, templates, vectors, arrays, preproccessor directives, friendship, operators and pointers (all of which you should probably know before attempting polymorphism):Note: It is not finished, but you can get the idea
main.cpp
main.h
这是使用多态类的基本示例
Here is a basic example using Polymorphic classes
多态性意味着多种形式,它用于让操作员在不同的情况下采取不同的行为。多态用于实现继承。例如,我们为类形状定义了一个fn draw(),那么可以实现draw fn来绘制圆形、盒子、三角形和其他形状。 (它们是类形状的对象)
Polymorphism means many forms as such it is used for an operator to act differently under different instances. Polymorphism is used to implement inheritance. For ex, we have defined a fn draw () for a class shape then the draw fn can be implemented for drawing circle, box, triangle and other shapes. ( which are objects of the class shape)
如果有人对这些人说“CUT”,
会发生什么?
所以上面的表示展示了 OOP 中的多态性(相同的名称,不同的行为)。
如果你要去参加面试,面试官要求你在我们坐在的同一个房间里讲述/展示多态性的实例,比如说
-答案-门/窗
想知道如何?
通过门/窗 - 一个人可以来,空气可以来,光可以来,雨可以来等等。
即一种形式不同的行为(多态性)。
为了更好地理解它并以简单的方式,我使用了上面的示例。如果您需要代码参考,请遵循上面的答案。
If anybody says CUT to these people
What will happen?
So above representation shows What is polymorphism (same name, different behavior) in OOP.
If you are going for an interview and interviewer asks you tell/show a live example for polymorphism in the same room we are sitting at, say-
Answer - Door / Windows
Wondering How?
Through Door / Window - a person can come, air can come, light can come, rain can come, etc.
i.e. One form different behavior(Polymorphism).
To understand it better and in a simple manner I used above example.. If you need reference for code follow above answers.