• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

C++面向对象编程

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

多态:使用相同的调用方法,调用不同对象,自己类里面函数

人类用手吃饭是本能;
英国人用刀叉吃饭;
中国人用筷子吃饭;
我们问“这个人怎么吃饭的?”,
应该根据其国别来回答,而不是简单地说“用手吃”。
这就是多态。

 1 #include <iostream>
 2 #include <string.h>
 3 #include <unistd.h>
 4 
 5 using namespace std;
 6 
 7 class Human{
 8 
 9 private:
10     int a;
11 public:
12     virtual void eating(void){cout<<"use hand to eat"<<endl;}//用到时会被替换成当前的
13     
14 
15 };
16 
17 class Englishhuman : public Human{
18 public:
19     void eating(void){cout<<"use knife to eat"<<endl;}
20 
21 };
22 
23 class Chinese : public Human{
24 public:
25     void eating(void){cout<<"use chopsticks to eat"<<endl;}
26 
27 };
28 
29 void test_eating (Human &h)
30 {
31     h.eating();
32 }
33 
34 int main(int argc,char **argv)
35 {
36     Human h;
37     Englishhuman e;
38     Chinese c;
39 
40     test_eating(h);
41     test_eating(e);
42     test_eating(c);
43 
44     cout<<"sizeof(Human) = "<<sizeof(h)<<endl;
45     cout<<"sizeof(Englishhuan) = "<<sizeof(e)<<endl;
46     cout<<"sizeof(Chinese) = "<<sizeof(c)<<endl;
47 
48     return 0;
49 }
View Code

原理:
对于虚函数,采用动态联编:有虚函数的对象里有一个指针,指向虚函数表;
调用虚函数时,会根据对象里的指针找到表,从表中取出函数来执行
对于非虚函数,采用静态联编:编译时就确定调用哪个函数
差别:
静态联编效率高,动态联编支持多态

注意:由于继承了Human所以对应的与Human中函数相同的函数也为虚函数

 1 #include <iostream>
 2 #include <string.h>
 3 #include <unistd.h>
 4 
 5 using namespace std;
 6 
 7 class Human{
 8 public:
 9     void eating(void){cout<<"use hand to eat"<<endl;}
10     
11 
12 };
13 
14 class Englishhuman : public Human{
15 public:
16     void eating(void){cout<<"use knife to eat"<<endl;}
17 
18 };
19 
20 class Chinese : public Human{
21 public:
22     void eating(void){cout<<"use chopsticks to eat"<<endl;}
23 
24 };
25 
26 void test_eating (Human &p)
27 {
28     h.eating();
29 }
30 
31 int main(int argc,char **argv)
32 {
33     Human h;
34     Englishhuman e;
35     Chinese c;
36 
37     test_eating(h);/* Human &p = h里面的Person部分;
38                                * p引用的是"h里面的Person部分"
39                                */
40     test_eating(e);
41     test_eating(c);
42 
43     return 0;
44 }
View Code

多态的限制:

1.test_func(Human* h):
 test_func(Human& h):使用指针或引用来使用对象时,才有多态
 test_func(Human h):传值时,无多态

2.只有类的成员函数才能声明为虚函数

3.静态成员函数不能是虚函数

4.内联函数不能是虚函数(使用inline关键字的函数)

5.构造函数不能是虚函数

6.析构函数一般都声明为虚函数

7.重载:函数参数不同,不可设为虚函数

覆盖:函数参数、返回值相同,可以设为虚函数

8.返回值例外:

函数参数相同,但是返回值是当前对象的指针或引用时,
也可以设为虚函数(除此之外不可以设置为虚函数,否则会出现错误)

 1 #include <iostream>
 2 #include <string.h>
 3 #include <unistd.h>
 4 
 5 using namespace std;
 6 
 7 class Human{
 8 
 9 private:
10     int a;
11 public:
12     virtual void eating(void){cout<<"use hand to eat"<<endl;}//用到时会被替换成当前的
13     
14 
15 };
16 
17 class Englishhuman : public Human{
18 public:
19     void eating(void){cout<<"use knife to eat"<<endl;}
20 
21 };
22 
23 class Chinese : public Human{
24 public:
25     void eating(void){cout<<"use chopsticks to eat"<<endl;}
26 
27 };
28 
29 void test_eating (Human h)//传值时没有对态
30 {
31     h.eating();
32 }
33 
34 int main(int argc,char **argv)
35 {
36     Human h;
37     Englishhuman e;
38     Chinese c;
39 
40     test_eating(h);
41     test_eating(e);
42     test_eating(c);
43 
44     cout<<"sizeof(Human) = "<<sizeof(h)<<endl;
45     cout<<"sizeof(Englishhuan) = "<<sizeof(e)<<endl;
46     cout<<"sizeof(Chinese) = "<<sizeof(c)<<endl;
47 
48     return 0;
49 }
View Code

对应第六点

 1 #include <iostream>
 2 #include <string.h>
 3 #include <unistd.h>
 4 
 5 using namespace std;
 6 
 7 class Human{
 8 
 9 private:
10     int a;
11 public:
12     virtual void eating(void){cout<<"use hand to eat"<<endl;}//用到时会被替换成当前的
13     virtual ~Human(){cout<<"~Human()"<<endl;}
14     
15 
16 };
17 
18 class Englishhuman : public Human{
19 public:
20     void eating(void){cout<<"use knife to eat"<<endl;}
21     virtual ~Englishhuman(){cout<<"~Englishman()"<<endl;}
22 };
23 
24 class Chinese : public Human{
25 public:
26     void eating(void){cout<<"use chopsticks to eat"<<endl;}
27     virtual ~Chinese(){cout<<"~Chinese()"<<endl;}
28 };
29 
30 void test_eating (Human h)
31 {
32     h.eating();
33 }
34 
35 int main(int argc,char **argv)
36 {
37     Human* h = new Human;
38     Englishhuman* e = new Englishhuman;
39     Chinese *c = new Chinese;
40 
41     Human *p[3] = {h,e,c};
42     int i;
43 
44     for (i = 0; i < 3; i++)
45     {
46         p[i]->eating();
47         delete p[i];
48     }
49         
50     return 0;
51 }
View Code

对应第八点

 1 #include <iostream>
 2 #include <string.h>
 3 #include <unistd.h>
 4 
 5 using namespace std;
 6 
 7 class Human{
 8 
 9 private:
10     int a;
11 public:
12     virtual void eating(void){cout<<"use hand to eat"<<endl;}
13     virtual ~Human(){cout<<"~Human()"<<endl;}
14     virtual Human*  test(void){cout <<"Human\'s test"<<endl;return this;}
15     
16 
17 };
18 
19 class Englishhuman : public Human{
20 public:
21     void eating(void){cout<<"use knife to eat"<<endl;}//由于继承了Human所以次函数也为虚函数
22     virtual ~Englishhuman(){cout<<"~Englishman()"<<endl;}
23     virtual Englishhuman*  test(void){cout<<"Englishman\'s test"<<endl;return this;}
24 };
25 
26 class Chinese : public Human{
27 public:
28     void eating(void){cout<<"use chopsticks to eat"<<endl;}////由于继承了Human所以次函数也为虚函数
29     virtual ~Chinese(){cout<<"~Chinese()"<<endl;}
30     virtual Chinese*  test(void){cout<<"Chinese\'s test"<<endl;return this;}
31 };
32 
33 void test_eating (Human &h)
34 {
35     h.eating();
36 }
37 
38 void test_return(Human &h)
39 {
40     h.test();
41 }
42 
43 int main(int argc,char **argv)
44 {
45     Human h;
46     Englishhuman e;
47     Chinese c;
48 
49     test_return(h);
50     test_return(e);
51     test_return(c);
52         
53     return 0;
54 }
View Code

类型转换:

C++中的类型转换:

dynamic_cast:

格式:dynamic_cast < type-id > ( expression )

该运算符把expression转换成type-id类型的对象。
Type-id必须是类的指针、类的引用或者void *;
如果type-id是类指针类型,那么expression也必须是一个指针;
如果type-id是一个引用,那么expression也必须是一个引用。

1. 用于多态场合,即:必须有虚函数
2. 主要用于类层次间的上行转换和下行转换,还可以用于类之间的交叉转换
3. 在类层次间进行上行转换时,dynamic_cast和static_cast的效果是一样的;
在进行下行转换时,dynamic_cast具有类型检查的功能,比static_cast更安全。

static_cast:

格式:static_cast < type-id > ( expression )

该运算符把expression转换为type-id类型,
但没有运行类型检查来保证转换的安全性。

1. 用于类层次结构中基类和子类之间指针或引用的转换。
2. 进行上行转换(把子类的指针或引用转换成基类表示)是安全的;
3. 进行下行转换(把基类指针或引用转换成子类指针或引用)时,由于没有动态类型检查,所以是不安全的。
4. 用于基本数据类型之间的转换,如把int转换成char,把int转换成enum:这种转换的安全性也要开发人员来保证。
5. 把void指针转换成目标类型的指针(不安全!!)
6. 把任何类型的表达式转换成void类型。
注意:static_cast不能转换掉expression的const、volitale、或者__unaligned属性。

reinterpret_cast:

格式:reinterpret_cast<type-id> (expression)
相当于C风格的用小括号"(type-id)"实现的强制类型转换

1. type-id必须是一个指针、引用、算术类型、函数指针或者成员指针
2. 它可以把一个指针转换成一个整数,也可以把一个整数转换成一个指针
3. 跟C风格的强制转换类似,没有安全性检查

const_cast:

格式:const_cast<type_id> (expression)

该运算符用来去除原来类型的const或volatile属性。
除了const 或volatile修饰之外, type_id和expression的类型是一样的。

 对应第十四天的文件夹


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
c#中高效的excel导入sqlserver的方法和获取excel结构的方法发布时间:2022-07-13
下一篇:
LeetCodeOnlineJudge题目C#练习-PlusOne发布时间:2022-07-13
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap