C++的重写,重载与充定义
来源:互联网 发布:ubuntu 麒麟wineqq 编辑:程序博客网 时间:2024/04/28 12:57
阅读《Effective C++》条款33的时候产生了疑惑,在重写与重定义上有所混淆。现将网上查阅的资料记录如下:
重写(override)
首先,重写是指派生类的方法覆盖基类的方法,要求方法名、方法的参数都相同。重写是C++中实现多态这个特性基础。重写又称为覆盖,是指派生类函数覆盖基类函数,与重定义不同,重写要求被重写的基类函数为虚函数。
例如下面的代码:
<code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">class Base{<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span>: <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">virtual</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> <span class="hljs-title" style="box-sizing: border-box;">Total</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> unit_price, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> num) = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;};class Derived :<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> Base{<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span>: <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">virtual</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> <span class="hljs-title" style="box-sizing: border-box;">Total</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> unit_price, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> num) { cout << <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"test"</span> << endl; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>; }};class Child :<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> Derived{<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span>: <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> <span class="hljs-title" style="box-sizing: border-box;">Total</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> unit_price, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> num) { <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> unit_price*num; }};</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li></ul>
总结一下,重写是指派生类重新定义了基类的虚函数,基类函数必须有virtual关键字修饰,不能有static关键字;返回值类型必须是相同的,或者是协变的;此外重写函数的访问修饰符可以不同。
注意:一般重写要求函数具有完全相同的入参,否则就会提示错误,而这个规则对于协变而言则有所放松。覆盖的返回值不区分基类或者派生类,如下代码:
<code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">class Base{<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span>: <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">virtual</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> <span class="hljs-title" style="box-sizing: border-box;">Total</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> unit_price, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> num) { cout << <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Base"</span> << endl; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>; }};class Derived :<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> Base{<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span>: <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">virtual</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> <span class="hljs-title" style="box-sizing: border-box;">Total</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> unit_price, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> num) { cout << <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"test"</span> << endl; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>; }};<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//协变</span>class Father{<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span>: <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">virtual</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span> Base& <span class="hljs-title" style="box-sizing: border-box;">getClass</span>() = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;};class Child{ <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">virtual</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span> Derived& getClass() { Derived ret; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> ret; }};</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li></ul>
在上面协变的例子中,要求Base和Derived两个类必须在使用前被完整的定义。
协变返回类型的优势在于,若是我们使用Father,就能获得一个抽象的Base,如果我们正在处理Child,就会获得一个Derived。协变的返回机制将我们从这样一种处境中解脱出来:不得不使用易于出错的转换操作来“重新”提供类型信息,而这种信息是一开始就不应该丢掉的。
重载(overload)
然后是重载(overload),重载是应用于相同作用域之内的同名函数,由于参数列表不同而产生的不同的实现方法。此处提到的作用域有:全局作用域、局部作用域以及类作用域,当在同一个作用域内的时候同名的函数或者称之为方法,由于参数列表的不同,而获得的不同的函数。
<code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> Sum(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> a, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> b);<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> Sum(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> a, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> b, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> c);<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> Sum(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">float</span> a, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">float</span> b);</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>
重载是一种语言特性,是一种语法规则,与多态无关,与面向对象无关。
重定义
重定义则是经常出现在基类和派生类之间,归结起来有如下的特点:
1)不在同一个作用域,主要是指类作用域,分别位于基类和派生类之中;
2)函数名称相同,但是返回值可以不同;
3)参数不同时,无论有没有virtual关键字,基类的函数都会被隐藏;参数相同时,但是基类函数没有关键字virtual,此时基类函数被隐藏。
例如:
<code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">class Base{<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span>: <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">virtual</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">double</span> <span class="hljs-title" style="box-sizing: border-box;">Total</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">double</span> a, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">double</span> b) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> a + b; } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> Print() { cout << <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Base"</span> << endl; } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> Sum(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> a, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> b);<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span>: //};class Derived :<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> Base{<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span>: <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">virtual</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">double</span> <span class="hljs-title" style="box-sizing: border-box;">Total</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">double</span> a, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">double</span> b, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">double</span> c) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> a + b + c; } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> Print() { cout << <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Derived"</span> << endl; } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> Sum(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> a, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> b, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> c);};</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li></ul>
在运行Derived的实例的时候可以很容易的发现,基类中Sum函数被隐藏了。因此重定义又称为隐藏,是指派生类的函数屏蔽了与其同名的基类函数。
<code class="hljs perl has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> _tmain(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> argc, _TCHAR* argv[]){ Derived test; test.Print(); Derived test_b; Base <span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*p</span>; p = new Derived; p->Print(); Base <span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*p_2</span>; p_2 = &test_b; p_2->Print(); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">delete</span> p; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">system</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"pause"</span>); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li></ul><div class="save_code tracking-ad" data-mod="popu_249" style="box-sizing: border-box; position: absolute; width: 105px; height: 60px; right: 30px; top: 5px; color: rgb(255, 255, 255); cursor: pointer; z-index: 2;"><a target=_blank target="_blank" style="box-sizing: border-box; color: rgb(12, 137, 207);"><img src="http://static.blog.csdn.net/images/save_snippets.png" style="border: none; box-sizing: border-box;" alt="" /></a></div>
例如上面的类,我们在如上调用的时候得到了下面的输出:
- C++的重写,重载与充定义
- 重载、重写与重定义
- 重载重写与重定义
- [C++]函数的重载、重写和重定义的区别
- C++_重载、重写和重定义的区别
- C++_重载、重写和重定义的区别
- C++中的重载重写与重定义
- C++ 重载 重写与重定义
- C++的重写,重载,重定义
- C++的重写,重载,重定义
- C++中的的重写,重载,重定义
- C++的重写,重载,重定义
- C++的重写,重载,重定义
- 重写、重载和重定义的区别
- 重写、重载和重定义的区别
- C++的重写,重载,重定义
- C++重写/重载/重定义的比较
- 重写,重载的定义和区别
- UI调试神器 for ios:Reveal的使用与破解
- PHP的压力测试工具ab.exe 和mpm介绍提高并发数
- 让Openwrt 默认开启wifi
- conv2函数(MATLAB)
- Service服务
- C++的重写,重载与充定义
- PATL2-006. 树的遍历
- tableviewcell 被选中时,label的背景色改变
- POJ 3264 Balanced Lineup 线段树基础
- 利用ajax无刷新验证注册信息
- 深度学习(四十)caffe使用点滴记录
- PAT甲级1001. A+B Format(20)
- 算法之 排序算法 (三) Java
- 单循环链表中设置尾指针比设置头指针更好的原因