对C++中的继承概念一直比较陌生,下面通过几道题来学习它。
1.下面描述中,表达错误的是(BCD)
A.公有继承时基类中的public成员在源生类中仍是public的 正确
B.公有继承时基类中的private成员在源生类中仍是public的 错误,不可见
C.私有继承时基类中的protected成员在源生类中仍是public的 错误,private
D.私有继承时基类中的public成员在源生类中仍是public的 错误,private
解释:
public | protected | private | |
公有继承 | public | protected | 不可见 |
私有继承 | private | private | 不可见 |
保护继承 | protected | protected | 不可见 |
通过下面的程序来学习:
#include<iostream>
using namespace std;
//
class A //父类
{
private:
int privatedateA;
protected:
int protecteddateA;
public:
int publicdateA;
};
//
class B :public A //基类A的派生类B( 有继承)
{
public:
void funct()
{
int b;
b=privatedateA; //error:基类中私有成员在派生类中是不可见的
b=protecteddateA; //ok:基类的保护成员在派生类中为保护成员
b=publicdateA; //ok:基类的公共成员在派生类中为公共成员
}
};
//
class C :private A //基类A的派生类C(私有继承)
{
public:
void funct()
{
int c;
c=privatedateA; //error:基类中私有成员在派生类中是不可见的
c=protecteddateA; //ok:基类的保护成员在派生类中为私有成员
c=publicdateA; //ok:基类的公共成员在派生类中为私有成员
}
};
//
class D :protected A //基类A的派生类D(保护继承)
{
public:
void funct()
{
int d;
d=privatedateA; //error:基类中私有成员在派生类中是不可见的
d=protecteddateA; //ok:基类的保护成员在派生类中为保护成员
d=publicdateA; //ok:基类的公共成员在派生类中为保护成员
}
};
//
int main()
{
int a;
B objB;
a=objB.privatedateA; //error:基类中私有成员在派生类中是不可见的,对对象不可见
a=objB.protecteddateA; //error:基类的保护成员在派生类中为保护成员,对对象不可见
a=objB.publicdateA; //ok:基类的公共成员在派生类中为公共成员,对对象可见
C objC;
a=objC.privatedateA; //error:基类中私有成员在派生类中是不可见的,对对象不可见
a=objC.protecteddateA; //error:基类的保护成员在派生类中为私有成员,对对象不可见
a=objC.publicdateA; //error:基类的公共成员在派生类中为私有成员,对对象不可见
D objD;
a=objD.privatedateA; //error:基类中私有成员在派生类中是不可见的,对对象不可见
a=objD.protecteddateA; //error:基类的保护成员在派生类中为保护成员,对对象不可见
a=objD.publicdateA; //error:基类的公共成员在派生类中为保护成员,对对象不可见
return 0;
}
2.关于子类型的描述中,( C)是错误的?
A.在公有继承下,派生类是基类的子类型
B.子类型关系是不可逆的
C.子类型就是指派生类是基类的子类型
D.一种类型当它至少提供了另一种类型的行为,则这种类型是另一种类型的子类型
3.C++类的继承中构造函数和析构函数调用顺序
这个比较困难,通过一个程序来学习:
/*当建立一个对象时,首先调用基类的构造函数,然后调用下一个派生类的
构造函数,依次类推,直至到达派生类次数最多的派生次数最多的类的构造函数为止。
简而言之,对象是由“底层向上”开始构造的。因为,构造函数一开始构造时,总是
要调用它的基类的构造函数,然后才开始执行其构造函数体,调用直接基类构造函数时,
如果无专门说明,就调用直接基类的默认构造函数。在对象析构时,其顺序正好相反。
下面的这个程序说明这个问题*/
//-------------------------------------------------
#include <iostream>
using namespace std;
class Shape
{
public:
void Draw() {cout<<"Base::Draw()"<<endl;}
void Erase() {cout<<"Base::Erase()"<<endl;}
Shape() {Draw();} //基类构造函数,调用上面的Draw函数体
virtual ~Shape() {Erase();}//基类析构函数,调用上面的Erase函数体
};
//-------------------------------------------------
class Polygon:public Shape
{
public:
Polygon() {Draw();}
void Draw() {cout<<"Polygon::Draw()"<<endl;}
void Erase() {cout<<"Polygon Erase()"<<endl;}
~Polygon() {Erase();}
};
//--------------------------------------------------
class Rectangle:public Polygon
{
public:
Rectangle() {Draw();}
void Draw() {cout<<"Rectangle::Draw()"<<endl;}
void Erase() {cout<<"Rectangle Erase()"<<endl;}
~Rectangle() {Erase();}
};
//--------------------------------------------------
class Square:public Rectangle
{
public:
Square() {Draw();}
void Draw() {cout<<"Square::Draw()"<<endl;}
void Erase() {cout<<"Square Erase()"<<endl;}
~Square() {Erase();}
};
//--------------------------------------------------
int main()
{
Polygon c;
Rectangle s;
Square t;
cout<<"------------------------------------------"<<endl;
return 0;
}
//------------------------------------------
运行结果:
Base::Draw()
Polygon::Draw()
Base::dRAW()
Polygon::Draw()
Rectangle::Draw()
Base::dRAW()
Polygon::Draw()
Rectangle::Draw()
Square::Draw()
------------------------------------------
Square Erase()
Rectangle Erase()
Polygon Erase()
Base::Erase()
Rectangle Erase()
Polygon Erase()
Base::Erase()
Polygon Erase()
Base::Erase()
Press any key to continue
题库的题,随便看看~
4.没有指明访问权限的类成员,其访问权限默认为( B )。
A.公有访问权限 B.私有访问权限
C.保护访问权限 D.不能确定?
5.关于构造函数的说法,下面不正确的是(A)。
A.如果类中没有定义默认构造函数,则系统会为该类生成一个默认构造函数。
B.默认的构造函数没有参数。
C.构造函数在对象创建时被自动调用。
D.构造函数没有返回值。
解释:应该是类中没有定义任何构造函数,系统才会为该类生成一个默认的构造函数
6.关于析构函数,下列说法错误的是(C)。
A.析构函数没有参数
B.析构函数没有返回值
C.析构函数可以重载
D.如果没有定义类的析构函数,系统会帮我们创建一个析构函数。
解释:C:一个类中只能定义一个析构函数,否则会造成同一个对象的多次删除,而构造函数可以根据不同的参数和类型进行多次重载