- 关于类之间继承有关的
- 若存在虚函数,基类的析构函数应为虚析构。且在整个过程中析构可访问,且不是删除的。
- 成员函数与继承
- 一种是基类希望其派生类进行覆盖的函数,即虚函数
- 另一种是基类希望派生类直接继承而不要改变的函数
- 关于虚函数需要弄清楚的是虚函数是当在动态绑定时的一种技术,继承的一种补充。虚函数提供了一种通过基类指针访问继承类的方法的途径。
- 对于继承来说,继承类完全继承了基类的所有方法(以访问限制符有关),若以继承类访问基类的方法,只要在限制范围内,完全可以,所以,此处,要多留心的若继承类与基类重名函数同名,同参的问题,此时继承类的方法变会覆盖基类
#include <iostream> using namespace std; struct s{ virtual void func(){ cout << "this is a virtual fucntion"<<endl; } void func1(){ cout << "this is a non-virtual function!"<<endl; } void func3(){ cout << "this is in s of func3"<<endl; } virtual ~s(){ } }; struct p:public s{ void func1(){ cout << " this is in class p"<<endl; } void func2(){ cout <<" this is func2 in class p"<<endl; } void func() override{ cout << "this is in p func virtual;"<<endl; } }; int main() { p a; a.func1();// this is in class p a.func3();//this is in s of func3 s* b= &a; b->func();//this is in p func virtual; }
- 防止继承的发生,final修饰符可以修饰类,也可以修饰virtual 函数,其意义对于类是不可继承,于虚函数是不能再重载。另还有一个限定符override,其概念在继承类的中函数中,其表明此函数是覆盖基类中的虚函数的,若在基类无此函数名,便会在编译时报错。
- 若用基类指针调用一个虚函数,若只是调用基类方法的,就用作用域指明方法即可,如 p->base::func();
- 关于纯虚函数只有在类内部的虚函数声明语句处,有纯虚函数的类为虚类。虚类不可实例化。
- 友元关系不能传递,同样的友元关系不能继承。
- 派生类的作用域位于基类的作用域之内,所以在派生类中调用基类和派生类同名函数时,若需调用基类的需通过基类域作用域限制如base::basefunc();声明在内层作用域的函数并不会重载声明在外导作用的函数。所以若基类的函数与派生类的函数重名,哪怕方法不同,也将会被派生类覆盖。
#include <iostream> using namespace std; struct s { void func3(){ cout << "this is in s of func3"<<endl; } virtual ~s(){ } }; struct p:public s{ void func3(int k) { cout << "this is in p func virtual;"<<endl; } }; int main() { p a; //a.func3();//同名函数,将会覆盖,由于参数不同,导致调用失败。 a.s::func3();//可以通过基类方法直接调用。 a.func3(1); }
- 若存在虚函数,基类的析构函数应为虚析构。且在整个过程中析构可访问,且不是删除的。
- 派生类的构造函数在其初始化阶段不仅要构造自己还要完成基类的构造,因此派生类的拷贝构造、移动构造函数在拷贝和移动自有成员的同时,也要拷贝和移动基类部分的成员。同样派生类的赋值也必须也为其基类赋值。但派生类的析构函数和基类的析构函数是分别
- 如果基类中的默认构造函数、拷贝构造函数、拷贝赋值运算符或析构函数是被删除的函数或者不可访问的,相应的其继承类中相应的函数也将地是删除的。
#include <iostream> using namespace std; struct s { s()=default; s(s& t)=delete; void func3(){ cout << "this is in s of func3"<<endl; } virtual ~s(){ } }; struct p : public s{ }; int main() { p t; //p q =t; 由于基类拷贝构造delete,所以在继承类中此也将为delete }
- 如果一个基类有一个不可访问或删除的析构函数,则派生类中合成的默认、拷贝构造函数将是删除的,因为编译器无法销毁派生类中构造的基类的部分。当然同样的问题也存在移动构造函数中。
- 一般情况下,基类都会定义一个虚析构函数。因此在默认情况下,基类通常不含有合成的移动操作,而且在它的派生类中也没有合成的移动操作。
- 在定认派生类的拷贝和移动、赋值函数中,我们一般调用先调用基类的相应的方法。而析构函数仅负责销毁本类,而不涉及到基类。
- 若在构造函数、析构函数中若以基类指针调用虚函数,其并不会按照预想调用相应的派生类的实现,而是仅会调用本类的方法,原因是在构造时,派生类未生成,在析构时,派生类已销毁,故此时并无派生类的方法。
- 构造函数的继承,这个东西可以少写些代码,不过总是觉得意义模糊。
#include <iostream> using namespace std; struct s { s(){} s(double k){} s(int i ,int j){} virtual ~s(){ } }; struct p : public s{ using s::s;//继承了基类的方法, }; int main() { p a(.2); //在p中会直接生成 p(double k):s(k){} p b(23,22);//在这中直接生成 p(int i ,int j):s(i,j){} }
- 这里有几点需要注意的是,派生类可以继承一部分构造函数,但如果派生类中构造函数与基类有相同参数列表不会继承
- 另一个是默认、拷贝和移动构造函数不会被继承。这些构造函数按照正常规则被合成。
- 最后关于多重继承与虚继承,为了在继承过程中,仅产生一份基类,产生了虚继承以及相应的虚基类的问题,所谓虚基类便是在整个继承体系中仅产生一个基类的复本。其他的算了吧。
c++/c学习笔记 --(7)
最新推荐文章于 2024-06-06 19:33:24 发布