首页 / C++ / C++基类、派生类、虚函数的几个知识点
C++基类、派生类、虚函数的几个知识点
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了C++基类、派生类、虚函数的几个知识点,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含3901字,纯文字阅读大概需要6分钟。
内容图文
1.尽管派生类中含有基类继承来的成员,但派生类初始化这部分变量需要调用基类的构造函数。
1 class A 2 { 3 private: 4 int x; 5 virtual void f(){cout<<"A f"<<endl;} 6 public: 7 A(/* args */){x=1;cout<<"A构造"<<endl;} 8 ~A(){} 9 friend void p(const A& a){cout<<a.x;} 10 }; 11 class B:A{ 12 public: 13 void f() override {cout<<"B f"<<endl;} 14 operator A()const {} 15 }; 16 int main() 17 { 18 B x; 19 system("pause"); 20 return 0; 21 }
2.如果基类定义了一个静态成员,则整个继承体系中只存在该成员的唯一定义。并且不论基类派生出多少派生类,该静态成员只存在唯一实例。
并且属性也一致。基类中某静态成员是public,派生类中也是public。如果基类中是private,那么派生类也无法调用该静态成员。
1 /* 基类的静态成员 */ 2 3 #include<iostream> 4 5 using namespace std; 6 7 class base 8 { 9 public: 10 static int num; 11 12 base() 13 { 14 num+=1; 15 } 16 17 ~base() 18 { 19 num-=1; 20 } 21 }; 22 23 // 基类定义的静态成员,被所有派生类共享 24 // 起到计数器的作用,自身还有所有派生类对象的个数 25 // 遵循私有 公有 保护的继承机制 访问不同 26 // 可以通过父类 子类对象访问 还可以通过父类 子类类名访问 27 int base::num = 0;// 类的静态成员 28 29 class basenew : public base 30 { 31 32 }; 33 34 class basenewx : public basenew 35 { 36 37 }; 38 39 40 void main() 41 { 42 basenew *p = new basenew[100]; 43 44 base *p1 = new base[40] 45 46 basenewx *p2 = new basenewx[50]; 47 48 cout << p->num << endl;// 190 49 cout << p1->num << endl;// 190 50 cout << p2->num << endl;// 190 51 52 53 cin.get(); 54 }
3.如果不想让某个类被继承,在类名后加final关键字。
final除了可以修饰类外,还可以修饰成员函数。还可以指明某个基类的虚函数不能被其派生类版本覆盖,如下:
首先要明确覆盖(override)与重载(overload)的定义,区别出什么是覆盖和重载:
覆盖就是派生类中虚成员函数覆盖基类中同名且参数相同的成员函数。
1 class A 2 { 3 public: 4 A(/* args */){} 5 virtual void f()final {} 6 virtual ~A(){} 7 }; 8 class B:public A{ 9 public: 10 void f(int x){}//重载(overload) 11 void f(){} //覆盖(override,非法,因为A中的f声明了final) 12 };
4.派生类对象是基类对象,派生类中包含有基类的成员。基类对象不是派生类对象,它不能包含派生类型的成员。
派生类可以向基类转化(仅限指针和引用),基类不能向派生类转化(毕竟派生类有多余的数据,基类没法自己生成)
如果用派生类对象为一个基类对象初始化或者赋值,只有其中的基类部分会被拷贝/移动/赋值,它的派生类部分会被忽略。
1 class A 2 { 3 private: 4 int x; 5 public: 6 A(/* args */){x=1;cout<<"A构造"<<endl;} 7 virtual ~A(){} 8 }; 9 class B:public A{ 10 11 }; 12 int main() 13 { 14 A x; 15 B y; 16 A* p=&y;//正确,将基类指针指向派生类变量,派生类指针隐式转换为基类指针。 17 B* q=&x;//错误 18 system("pause"); 19 return 0; 20 }
5.动态绑定(即dynamic bninding)只有当我们通过指针或者引用调用虚函数时才会发生。
由于继承导致对象的指针和引用具有两种不同的类型:静态类型和动态类型。
静态类型:指针或者是引用声明时的类型。
动态类型:由实际指向的类型确定。
其中静态类型编译时就已经确定,动态类型只有到运行的时候才能知道。所以如果用普通类类型调用虚函数,编译时就会把要调用的虚函数版本确定下来。
1 class A 2 { 3 public: 4 A(/* args */){} 5 virtual void f(){cout<<"基类的f"<<endl;} 6 virtual ~A(){} 7 }; 8 class B:public A{ 9 public: 10 void f(){cout<<"派生类的f"<<endl;} 11 }; 12 void F(A& p){ 13 p.f(); 14 } 15 int main() 16 { 17 A x; 18 B y; 19 F(x); 20 F(y); 21 system("pause"); 22 return 0; 23 }
可以看到同一个函数F,因为调用不同类型实参,最终在内部调用了不同版本的f函数,这就是动态绑定。
如果F的形参改成普通类型,那么两次都会调用基类的f函数,其中F(y)会把y隐式类型转换为一个A类型的临时变量传给形参。
6.如果一个派生类虚函数需要调用其基类版本,但没有使用“基类::”修饰,则运行时该调用会被解析为对其自身的调用,这将导致无限递归。
7.派生类中的虚函数可以在形参后加override,显式告知编译器该虚函数覆盖了其基类版本。
内容总结
以上是互联网集市为您收集整理的C++基类、派生类、虚函数的几个知识点全部内容,希望文章能够帮你解决C++基类、派生类、虚函数的几个知识点所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。