第三章 习题

第 3章 类 与 对 象
一、 填空题
(1) 类 定 义 中 关 键 字 private 、 public 和 protected 以后的成员的访问权限分别是私有、公 有和保护。如果没有使用关键字,则所有成员默认 定义为 private 权限。具有 public 访问权限的数 据成员才能被不属于该类的函数所直接访问。 (2) 定义成员函数时,运算符“∷”是作用域运 算符, “ MyClass ∷”用于表明其后的成员函数是在 “ MyClass 类”中说明的。
(3) 在程序运行时,通过为对象分配内存来创建 对象。在创建对象时,使用类作为样板,故称对象 为类的实例。
(4) 假定 Dc 是一个类,则执行“ Dc a[10], b (2) ”语句时,系统自动调用该类构造函数的次数 为 11。
(5) 对于任意一个类, 析构函数的个数最多为 1个。
(6) delete运算符通常用于实现释放该类对象 中指针成员所指向的动态存储空间的任务。
(7) C++程序的内存格局通常分为 4个区:数 据区、代码区、栈区和堆区。
(8) 数据定义为全局变量,破坏了数据的 封装 性; 较好的解决办法是将所要共享的数据定义为 类的 静态成员。
(9) 静态数据成员和静态成员函数可由 任意访 问权限许可的函数访问。
(10) 友元函数和 友元类统称为友元。 (11) 友元的正确使用能提高程序的效率,但破 坏了类的封装性和数据的隐蔽性。
(12) 若需要把一个类 A 定义为一个类 B 的友元 类,则应在类 B 的定义中加入一条语句: friend class A; 。
二、 选择题(至少选一个,可以多选)
(1) 以下不属于类访问权限的是( B ) 。
A. public B. staticC. protectedD. private 

 (2) 有关类的说法不正确的是( BC ) 。
A. 类是一种用户自定义的数据类型 B. 只有类的成员函数才能访问类的私有数据成员
C. 在类中,如不做权限说明,所有的数据成员都 是公有的
D. 在类中,如不做权限说明,所有的数据成员都 是私有的
(3) 在类定义的外部,可以被任意函数访问的 成员有( C ) 。
A. 所有类成员 B. private 或 protected 的 类成员
C. public的类成员 D. public或 private 的 类
(4) 关于类和对象的说法( C )是错误的。
A. 对象是类的一个实例
B. 任何一个对象只能属于一个具体的类
C. 一个类只能有一个对象
D. 类与对象的关系和数据类型与变量的关系相似
(5) 设 MClass 是一个类, dd 是它的一个对象, pp 是指向 dd 的指针, cc 是 dd 的引用,则对成员 的访问,对象 dd 可以通过( B )进行,指针 pp 可以通过( D )进行,引用 cc 可以通过( B ) 进行。
A. ∷ B. . C. & D. ->
(6) 关于成员函数的说法中不正确的是 ( C ) 。 A. 成员函数可以无返回值
B. 成员函数可以重载 C. 成员函数一定是内联函数 D. 成员函数可以设定参数的默认值 

 (7) 下面对构造函数的不正确描述是( B ) 。 A. 系统可以提供默认的构造函数
B. 构造函数可以有参数,所以也可以有返回值 C. 构造函数可以重载 D. 构造函数可以设臵默认参数
(8) 假定 A 是一个类,那么执行语句“ A a, b (3) , *p; ”调用了( B ) 次构造函数。 A. 1 B. 2 C. 3 D. 4
(9) 下面对析构函数的正确描述是( AC ) 。 A. 系统可以提供默认的析构函数 B. 析构函数必须由用户定义 C. 析构函数没有参数 D. 析构函数可以设臵默认参数
(10) 类的析构函数是( D )时被调用的。 A. 类创建 B. 创建对象 C. 引用对象 D. 释放对象
(11) 创建一个类的对象时, 系统自动调用 ( B ) ; 撤销对象时,系统自动调用( C ) 。
A. 成员函数 B. 构造函数 C. 析构函数 D. 复制构造函数
(12) 通常拷贝构造函数的参数是( C ) 。 A. 某个对象名 B. 某个 对象的成员名
C. 某个对象的引用名 D. 某个 对象的指针名
(13) 关于 this 指针的说法正确的是( B ) 。
A. this指针必须显式说明 B. 当创建一个对象后, this 指针就指向该对象
C. 成员函数拥有 this 指针 D. 静态成员函数拥有 this 指针。
(14) 下列关于子对象的描述中, ( B )是错误 的。
A. 子对象是类的一种数据成员,它是另一个类的 对象
B. 子对象可以是自身类的对象
C. 对子对象的初始化要包含在该类的构造函数中 D. 一个类中能含有多个子对象作其成员
(15) 对 new 运算符的下列描述中, ( B )是错 误的。
A. 它可以动态创建对象和对象数组 B. 用它创建对象数组时必须指定初始值 C. 用它创建对象时要调用构造函数
D. 用它创建的对象数组可以使用运算符 delete 来 一次释放
(16) 对 delete 运算符的下列描述中, ( D ) 是错误的。
A. 用它可以释放用 new 运算符创建的对象和对象 数组
B. 用它释放一个对象时,它作用于一个 new 所返 回的指针
C. 用它释放一个对象数组时,它作用的指针名前 须加下标运算符[ ]
D. 用它可一次释放用 new 运算符创建的多个对象

17)关于静态数据成员,下面叙述不正确的是( C )

A 使用静态数据成员,实际是为了消除全局变量

B.可以使用“对象名,静态成员”或者“类名::静态成员”来访问静态数据成员

C.静态数据成员只能在静态成员函数中引用

D.所有对象的静态数据成员占用同一内存单元

18) 对静态数据成员的不正确描述是( CD )。

A.静态成员不属于对象,是类的共享成员

B.静态数据成员要在类外定义和初始化

C.调用静态成员函数时要通过类或对象激活,所以静态成员函数拥this指针

D.只有静态成员函数可以操作静态数据成员

19)下面的选项中,静态成员函数不能直接访问的是( D )。

 A.静态数据成员  B,静态成员函数

 C.类以外的函数和数据   D.非静态数据成员

20)在类的定义中,引人友元的原因是( A )。

  A.提高效率  B.深化使用类的封装

C.提高程序的可能性   D.提高数据的隐秘性

21)友元类的声明方法有( A )

A.friend class<类名>     B.youyuan class<类名>

C.class friend <类名>   d.friends class<类名>

22)下面对友元的错误描述是( D )

A.关键字friend 用于声明友元

B.一个类中的成员函教可以是另一个类的友元

C.友元函数访问对象的成员不受访同特性影响

D.友元函数通过this 指针访问对象成员

23)下面选项中,( C )不是类的成员函数,

A.构造函数      B.析构函数      C.友元函数       D.拷贝构造函数

三、简答题

1) 类与对象有什么关系?

答:类是一种用户自己定义的数据类型,和其他数据类型不同的是,组成这种类型的不仅可以有数据,而且可以有对数据进行操作的函数。程序员可以使用这个新类型在程序中声明新的变量,具有类型的变量称为对象,创建对象时,类被用作样板,对象称为类的实例。

2) 类定义的-般形式是什么? 其成员有哪几种访问权限?

答:类定义的一般形式为:                                                                             class类名

{

    public:

         <公有数据和函数>

    protected:

         <保护数据和函数>

    private:

         <私有数据和函数>

};

成员的访问权限: public、 protected和private的访问权限分别有公有、私有和保护。

3)类的实例化是指创建类的对象还是定义类?

答:指创建类的对象。

4)什么是this指针? 它的主要作用是什么?

答:this指针是C++语言为成员函数提供的一个隐含对象指针,它不能被显性声明。

作用:this指针是一个局部量,局部于某个对象。不同的对象调用同一个成员函数时,编译器根据this指针来确定应该引用哪一个对象的数据成员。

5)什么叫做拷贝构造函数? 拷贝构造函数何时被调用?

 答:拷贝构造函数是一种特殊的构造函数,它的作用是用一个已经存在的对象去初始化另一个对象,为了保证所引用的对象不被修改,通常把引用声明为cons参数。

拷贝构造函数在以下3种情况下会被自动调用:

当用类的一个对象去初始化该类的另一个对象时。

当函数的形参是类的对象,进行形参实参的结合时。

当函数的返回值是类的对象,函数执行完成返回调用者时。

四、程序分析题

 (1)

#include<iostream>  

using namespace std;  

class Test  

{  

private:  

    int num;  

public:  

    Test();  

    Test(int n);  

};  

Test::Test()  

{  

    cout<<"Init defa"<<endl;  

    num=0;  

}  

Test::Test(int n)  

{  

    cout<<"Init"<<""<<n<<endl;  

    num=0;  

}  

int main()  

{  

    Test x[2];  

    Test y(15);  

    return 0;  

}  

运行结果:

分析:程序声明了2个对象x和y,类中有两个构造函数。一个默认的构造函数Test(),一个带有参数的构造函数Test(int n),在执行Test x[2]时,创建对象x,调用默认构造函数,由于对象x是对象数组,每个数组元素被创建时都需要调用构造函数,所以默认构造函数被调用了两次,输出1、2行

语句。接着执行Test y(15),创建对象y,调用带一个参数的构造函数,输出第三行结果。

(2)

#include<iostream>  

using namespace std;  

class Xx  

{  

private:  

    int num;  

public:  

    Xx(int x)  

    {  

        num=x;  

    }  

    ~Xx()  

    {  

        cout<<"dst"<<num<<endl;  

    }  

};  

int main()  

{  

    Xx w(5);  

    cout<<"Exit main"<<endl;  

    return 0;  

}  

运行 结果:

分析:首先执行Xx w(5)创建对象w,调用构造函数,num得到初始值为5.接着执行cout<<"Exit main<<endl输出语句,输出第一行结果。当程序结束时,释放对象w,析构函数被调用,输出第二行结果。

3)将例3.10中的Whole类如下修改,其他部分不变,写出输出结果。


#include<iostream>  

using namespace std;  

class Part  

{  

    public:  

        Part();  

        Part(int x);  

        ~Part();  

    private:  

        int val;  

};  

Part::Part()  

{  

    val=0;  

    cout<<"Default constructor of Part"<<endl;  

}  

Part::Part(int x)  

{  

    val=x;  

    cout<<"Constructor of Part"<<","<<val<<endl;  

}  

Part::~Part()  

{  

    cout<<"Destructor of Part"<<","<<val<<endl;  

}  

class Whole  

{  

    public:  

        Whole(int i);  

        Whole(){};  

        ~Whole();  

    private:  

         Part p1;  

         Part p2;         

  Part p3;  

};  

Whole::Whole(int i):p2(i),p1()  

{  

    cout<<"Constructor of Whole"<<endl;  

}  

Whole::~Whole()  

{  

    cout<<"Destructor of Whole"<<endl;  

}  

int main()  

{  

    Whole w(3);  

    return 0;  

}  

运行结果:



分析:程序Whole类中出现了类Part的3个对象p1、p2和p3作为该类的数据成员,则p1、p2和p3被称为子对象。当建立的Whole类的对象w时,子对象p1、p2和p3被建立,所指定的构造函数被执行。由于p1在Whole类中先说明,所以先执行它所使用的构造函数,即类Part的默认构造函数。接着p2执行它所使用的有参构造函数,最后初始化p3,由于Whole类构造函数的成员初始化列表中没有子对象p3进行初始化的选项,所以执行类Part的默认构造函数,当所有子对象被构造完成之后,对象w的构造函数才被执行,从而得到前4行输出结果。后4行是执行相应析构函数的输出结果。

(4)

#include<iostream>  

using namespace std;  

class Book  

{  

    public:  

       Book(int w);  

       static int sumnum;  

    private:  

        int num;  

};  

Book::Book(int w)  

{  

    num=w;  

    sumnum-=w;  

}  

int Book::sumnum=120;  

int main()  

{  

    Book b1(20);  

    Book b2(70);  

    cout<<Book::sumnum<<endl;  

    return 0;  

}  

运行结果:

分析:intBook::sumnum=120”这条语句是给sumnum初始化并给sumnum赋值120,“Book b1(20)”调用构造函数,这时sumnum的值变为100,接着又调用构造函数,sumnum的值就变成了30。

五、程序设计题

1)声明一个Cricle类,有数据成员radius(半径)、成员函数area(),计算圆的面积,构造一个Cricle的对象进行测试。

编写的程序如下:

#include<iostream>  

using namespace std;  

const float PI=3.14;  

class Circle  

{  

    public:  

        Circle(float r)  

        {  

            radius=r;  

        }  

         float area()  

        {  

            return radius*radius*PI;  

        }  

    private:  

    float radius;  

};  

int main()  

{  

    Circle c(6);  

    cout<<"圆的面积="<<c.area()<<endl;  

结果如下:



2)重新编写程序分析题(4)的程序,设计一个静态成员函数,用来输出程序分析题(4)中的静态数据成员的值。

编写的程序如下:

#include<iostream>  

using namespace std;  

class Book  

{  

    public:  

       Book(int w);  

       static int sumnum;  

       static int getsum()  

       {  

           return sumnum;  

       }  

    private:  

        int num;  

};  

Book::Book(int w)  

{  

    num=w;  

    sumnum-=w;  

}  

int Book::sumnum=120;  

int main()  

{  

    Book b1(20);  

    Book b2(70);  

    cout<<Book::getsum()<<endl;  

    return 0;  

}  

运行结果如下:
 

阅读更多

没有更多推荐了,返回首页