平台网站建设报价,高明网站开发,设计企业vi,百度灰色关键词代发文章参考#xff1a;https://blog.csdn.net/war1111886/article/details/8609957 
一 .继承中的访问权限关系 #xff11;#xff0e;基类#xff0c;父类#xff0c;超类是指被继承的类#xff0c;派生类#xff0c;子类是指继承于基类的类#xff0e;  
#xff12;… 
文章参考https://blog.csdn.net/war1111886/article/details/8609957 
一 .继承中的访问权限关系 基类父类超类是指被继承的类派生类子类是指继承于基类的类  
在C中使用 冒号表示继承如class A : public B表示派生类从基类继承而来 
派生类包含基类的所有成员而且还包括自已特有的成员派生类和派生类对象访问基类中的成员就像访问自已的成员一样可以直接使用不需加任何操作符但派生类仍然无法访问基类中的私有成员 
在中派生类可以同时从多个基类继承Java 不充许这种多重继承当继承多个基类时使用逗号将基类隔开 
基类访问控制符 class A : public B        基类以公有方式被继承 class A:private B        基类以私有方式被继承 class A:protected B    基类以受保护方式被继承如果没有访问控制符则默认为私有继承。 
6 protected 受保护的访问权限使用protected 保护权限表明这个成员是私有的但在派生类中可以访问基类中的受保护成员。派生类的对象就不能访问受保护的成员了。 
7 如果基类以public公有方式被继承则基类的所有公有成员都会成为派生类的公有成员受保护的基类成员成为派生类的受保护成员       如果基类以private私有被继承则基类的所有公有成员都会成为派生类的私有成员基类的受保护成员成为派生类的私有成员  如果基类以protected 受保护方式被继承那么基类的所有公有和受保护成员都会变成派生类的受保护成员 不管基类以何种方式被继承基类的私有成员仍然保有其私有性被派生的子类不能访问基类的私有成员 
例继承中的访问权限关系   
class A {int a;protected:int b;public:int c;A() { a  b  c  1; }};//类B以公有方式从基类A继承class B : public A {public:int d;B() {//a2;  //错误不能访问基类中的私有成员b  2;   //正确可以在类中访问基类中的受保护成员但类的对象不能访问基类中的受保护成员b在类B中仍然是受保护成员c  d  2;}}; //基类中的公有成员c在类B中仍然是公有成员//类C以受保护和私有方式从基类A继承。class C : protected A {public:int e;C() {//a3;  //错误不能访问基类中的私有成员b  c  e  3;}};//这里基类受保护成员b和公有成员c都成为类C中的受保护成员。class D : private A {public:D(){ b  c  4; }};//基类中的公有和受保护成员都成为了类D中的私有成员。//验证受保护和私有方式继承的访问权限。class C1 : public C {public:C1() { b  c  e  4; }};//正确;类A中的成员b和c在类C中是以受保护方式被继承的b和c都成为了类C中的受保护成员。class D1 : public D {public:D1() {//b5; //错误在A中受保护的成员b在类D中是以私有方式继承的这样b就成为了类D中的私有成员所以无法访问。//c5; //错误在A中公有的成员c在类D中是以私有方式继承的这样c就成为了类D中的私有成员所以无法访问。}};int main(){A m1;B m2;C m3;D m4;//coutm1.bm2.bm3.bm4.bendl;   //错误不能用类的对象访问受保护的成员只有在类中才能访问。cout  m1.c endl;cout  m2.c endl;//coutm3.cendl;    //错误类C是以受保护的方式从A继承的基类中的变量c在类C中就是受保护的所以类的对象不能访问//coutm4.cendl;    //错误类C是以私有的方式从A继承的基类中的变量c在类C中就是私有的所以类的对象不能访} 
二.覆盖和隐藏基类成员变量或成员函数 1 基类的成员变量或函数被覆盖 
如果派生类覆盖了基类中的成员函数或成员变量则当派生类的对象调用该函数或变量时是调用的派生类中的版本当用基类对象调用该函数或变量时是调用的基类中的版本。 
2 隐藏基类成员函数的情况 
如果在派生类中定义了一个与基类同名的函数不管这个函数的参数列表是不是与基类中的函数相同则这个同名的函数就会把基类中的所有这个同名的函数的所有重载版本都隐藏了这时并不是在派生类中重载基类的同名成员函数而是隐藏比如类A中有函数 f (int i , int j)和 f (int i)两个版本当在从A派生出的类B中定义了基类的 f() 函数版本时这时基类中的 f (int i)和f (int i , int j)就被隐藏了也就是说由类B创建的对象比如为m不能直接访问类A中的f(int i)版本即使用语句m.f(2)时会发生错误。 
3 怎样使用派生类的对象访问基类中被派生类覆盖或隐藏了的函数或变量 3.1 方法1   使用作用域运算符:: 在使用对象调用基类中的函数或变量时使用作用域运算符即语句m.A::f(2)这时就能访问基类中的函数或变量版本。注意访问基类中被派生类覆盖了的成员变量只能用这种方法       3.2方法2   使用using:: , 该方法只适用于被隐藏或覆盖的基类函数在派生类的类定义中使用语句using 把基类的字包含进来比如using A::f就是将基类中的函数f()的所有重载版本包含进来重载版本被包含到子类之后这些重载的函数版本就相当于是子类的一部分这时就可以用派生类的对象直接调用被派生类隐藏了的基类版本比如m.f(2)但是使用这种语句还是没法调用基类在派生类中被覆盖了的基类的函数比如m.f()调用的是派生类中定义的函数f要调用被覆盖的基类中的版本要使用语句m.A::f()才行。 
4 在派生类的函数中调用基类中的成员变量和函数的方法 
就是在函数中使用的被派生类覆盖的基类成员变量或函数前用作域解析符加上基类的类名即A::f()就是在派生类的函数中调用基类中被派生类覆盖了的函数f()的方法。 
5 派生类以私有方式被继承时改变基类中的公有成员为公有的方法 5.1使用:: 作用域运算符不提倡用这种方法在派生类的public 后面用作用域运算符把基类的公有成员包含进来这样基类的成员就会成为派生类中的公有成员了注意如果是函数的话后面不能加括号如A::f如果f是函数的话不能有括号。       5.2使用using语句现在一般用这种方法也是在派生类的public使用using把基类成员包函进来如using A::f。 
例隐藏或覆盖基类中的成员使用::作用域运算符访问 ———————————————— 版权声明本文为CSDN博主「Sherlock_Homles」的原创文章遵循CC 4.0 BY-SA版权协议转载请附上原文出处链接及本声明。 原文链接https://blog.csdn.net/Sherlock_Homles/article/details/82927515 
class A {int a;
protected:int b;
public:int c, d;void f(int i) {cout  class A  \n;}A() { a  b  c  d  1; }
};class B : public A {
public:int d;//覆盖基类中的成员变量d。B() {b  c  d  2;            //这里是给子类B中的成员变量d赋值而不是基类中的dA::d  3;} //给基类中被覆盖的成员d赋值注意在类中访问的被覆盖成员的方式。void f() {cout  class B  \n;  //在子类中重定义基类中的同名函数虽然参数列表不一样但同样会隐藏基类中的同名函数A::f(1);    //在函数中调用基类中被隐藏了的同名函数的方法使用作用域解析运算符。//f(1);       //错误因为基类中的函数被子类中的同名函数隐藏了在这里子类不知道有一个带参数的函数f。}
};int main() {B m;cout  m.d  \n;      //输出子类中的成员变量d的值注意派生类中覆盖了基类成员d.cout  m.A::d  \n;   //输出基类中的成员变量d的值注意这是使用对象访问被覆盖的基类成员的方式m.f();                    //调用子类中的不带参数的函数f。// m.f(2);                   //错误因为基类中的带一个参数的函数f被子类中的同名函数隐藏掉了不能这样访问须用作用域解析运算符来访问。m.A::f(1);} //使用子类对象访问基类中被隐藏的函数的方法。 
例使用using 语句以便访问基类中被隐藏的函数 
class A {int a;
protected:int b;
public:int c, d;void f() { cout  Amoren  \n; }void f(int i) { cout  class A  \n; }A() { a  b  c  d  1; }
};class B : public A {
public:int d;//覆盖基类中的成员变量d。B() {b  c  d  2;  //这里是给类B中的成员变量d赋值而不是基类中的dA::d  3;} //给基类中被覆盖的成员d赋值注意在类中访问的被覆盖成员的方式。using A::f;        //使用语句using把类A中的函数f包含进来以便以后可以直接访问基类被隐藏了的函数注意函数f没有括号void f() {cout  class B  \n;  //在子类中覆盖基类中的同名函数注意这里是覆盖同时会隐藏基类中的其他同名重载函数f(1);       //正确因为使用了using语句所以可以在类中直接使用基类中f函数的重载版本。A::f(2);    //正确虽然使用了using语句但同样可以按这种方法访问基类中的函数。A ma;ma.f();     //正确在子类中创建的基类对象可以直接用对象名调用基类中被子类覆盖或隐藏了的函数因为这时不会出现二义性。ma.f(1);    //正确在子类中创建的基类对象可以直接用对象名调用基类中被子类覆盖或隐藏了的函数因为这时不会出现二义性。}void g() {cout  this g  \n; f();        //正确但该语句访问的是子类中的不带参数函数f虽然在类中使用了using语句但直接调用被子类覆盖了的基类函数时不能使用这种方法A::f();     //正确调用被子类覆盖了的基类中的函数f注意虽然使用了using但要访问被子类覆盖了的函数只能这样访问。}
};
int main() {B m;m.f();       //调用子类中的不带参数的函数这里不会调用基类中的不带参数的被覆盖的函数f。m.A::f();    //调用基类中被子类覆盖了的函数f虽然子类使用了using语句但要访问基类中被覆盖的方法只能像这样使用。m.f(1);      //调用基类重载的f函数注意这里可以不用::运算符因为在子类中使用了using只要子类没有覆盖基类中的方法都可以这样直接调用。m.A::f(2);   //当然使用了using后也可以使用这种方法
}  
例派生类以私有方式被继承时改变基类中的公有成员为公有的方法 
class A {
public:int a, b;void f() { cout  f  \n; }void g() { cout  g  \n; }
};class B : private A {
public:A::f;         //使用::运算符使基类中的成员成为公有的。注意函数名后不能有括号。(C11标准不允许使用using A::f)A::a;         //(C11标准不允许使用using A::a)using A::g;   //使用using语句使基类中的成员函数g成为类B中的公有成员注意函数名后不能有括号。
};
int main() {B m;//m.b1;        //错误因为类B是以私有方式继承的类A中的成员在类B中是私有的这里不能访问私有成员。m.f();m.g();m.a  1;
} 
三.继承时的构造函数和析构函数问题 1 在继承中基类的构造函数构建对象的基类部分派生类的构造函数构建对象的派生类部分。 
2 当创建派生类对象时先用派生类的构造函数调用基类的构造函数构建基类然后再执行派生类构造函数构造派生类。 即先构造基类再构造派生类的顺序。执行析构函数的顺序与此相反。 
3 调用基类带参数的构造函数的方法 
在派生类的构造函数中使用初始化列表的形式就可以调用基类带参数的构造函数初始化基类成员如B():A(int i){}类B是类A的派生类。 
4 派生类的构造函数调用基类的构造函数的方法为 
4.1 如果派生类没有显示用初始化列表调用基类的构造函数时这时就会用派生类的构造函数调用基类的默认构造 函数构造完基类后才会执行派生类的构造函数函数体以保证先执行基类构造函数再执行派生类构造函数 的顺序如果基类没有默认构造函数就会出错。 4.2 如果派生类用 显示的初始化列表调用基类的构造函数时这时就会检测派生类的初始化列表当检测到显示调 用基类的构造函数时就调用基类的构造函数构造基类然后再构造派生类以保证先执行基类构造函数再执 行派生类构造函数的顺序如果基类没有定义派生类构造函数初始化列表调用的构造函数版本就会出错。 
5 如果在基类中没有定义默认构造函数但定义了其他构造函数版本这时派生类中定义了几个构造函数的不同版本 这时只要派生类有一个构造函数没有显示调用基类中定义的构造函数版本就会发生错误因为编译器会首先检查派 生类构造函数调用基类构造函数的匹配情况如果发现不匹配就会出错即使没有创建任何类的对象都会出错而 不管这个派生类的对象有没有调用派生类的这个构造函数。比如基类有一个构造函数版本A(int i)而没有定义默认 构造函数派生类B有这几个版本的构造函数B():A(4){}B(int i):A(5){}再有语句B(int i, int j){}没有显示调用 基类定义的构造函数而是调用基类的默认构造函数如果创建了B m和语句B m(1)时都会提示没有可用的基类默认 构造函数可用的错误虽然这时类B的对象m没有调用派生类B的带有两个形参的构造函数但同样会出错。 
6 同样的道理如果基类中定义了默认构造函数却没有其他版本的构造函数而这时派生类却显示调用了基类构造 函数的其他版本这时就会出错不管你有没有创建类的对象因为编译器会先在创建对象前就检查构造函数的匹 配问题。 
7 派生类只能初始化他的直接基类。比如类C是类B的子类而类B又是类A的子类这时class C:public B{public: B():A(){} };将会出错该语句试图显示调用类B的基类类A的构造函数这时会出现类A不是类C的基类的错误。 
8 继承中的复制构造函数和构造函数一样基类的复制构造函数复制基类部分派生类的复制构造函数复制派生类部 分。 
9派生类复制构造函数调用基类复制构造函数的方法为A(const A m):B(m){}其中B是基类A是派生类。 
10如果在派生类中定义了复制构造函数而没有用初始化列表显示调用基类的复制构造函数这时不管基类是否定义了 复制构造函数这时出现派生类对象的复制初始化情况时就将调用基类中的默认构造函数初始化基类的成员变量 注意是默认构造函数不是默认复制构造函数如果基类没有默认构造函数就会出错。也就是说派生类的复制构造函 数的默认隐藏形式是B(const B j):A(){}这里B是A的派生类也就是说如果不显示用初始化列表形式调用基类的 复制构告函数时默认情况下是用初始化列表的形式调用的是基类的默认构造函数。 
11当在派生类中定义了复制构造函数且显示调用了基类的复制构造函数而基类却没有定义基类的复制构造函数时 这时出现派生类对象的复制初始化情况就将调用基类中的默认复制构造函数初始化基类部分调用派生类的复制构 造函数初始化派生类部分因为复制构造函数只有一种形式即A(const A m){}比如当出现调用时A(const A m):B(m){}如果这时基类B没有定义复制构造函数则该语句将会调用派生类A的默认复制构造函数。 
12如果基类定义了复制构造函数而派生类没有定义时则会调用基类的复制构造函数初始化基类部分调用派生类 的默认复制构造函数初始化派生类部分。