【c++主题】一套不错的考试题

本文深入探讨了C++编程中常见的错误定义、不合法的定义、合法的定义、表达式有效性以及模板函数应用等多个核心问题。通过具体实例分析,详细解释了每个选项的正确性,并对错误进行了深入剖析,旨在帮助读者更好地理解C++编程规范,提高编程能力。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

http://blog.youkuaiyun.com/xscarlet/article/details/1702309

朋友搞到一套题,要我做做,看了看,有些细节的地方,对考试来说挺好的,不过实际编码中没人会编的像有些题似的那么隔路,发出来给路过的博友看看,如果我做的有什么不对的地方,请指出,感激不尽!

1.     <!--[endif]-->已知下面这些类型的声明

template <class elemType> class Array;

enum Status {...};

typedef string* Pstring;

下面哪一个对象的定义是错误的:     

  1. Array< int* &> pri( 1024 );
  2. Array< Array<int> > aai( 1024 );
  3. Array< Status > as( 1024 );
  4. Array< Pstring > aps( 1024 );

解释:首先要确定Array这个模板类里有一个构造函数,这个构造函数还必须接受一个整形或浮点形或可以转换到整形的参数。然后可以确定a选项是不对的。分析各选项,
B中要求这个类还要有一个无参的构造函数!因为Array<int>这样的类型在Array< >中初始化的时候,是被视为一个类类型的,而不是像int double 这样的内置类型,这样在Array<>的构造函数中就必须生成一系列Array<int>这样的类型,如果没有无参的构造函数,那么是错误的;
C
说明Array中存放的类型是Status;
D说明Array中存放的类型是string的指针;
A int型的指针的引用时不行的,但是如果改成int**是可以的

<!--[if !supportLists]-->

2.     <!--[endif]-->下面哪些定义不合法:       

<!--[if !supportLists]-->a.     <!--[endif]-->int car = 1024, auto = 2048;

<!--[if !supportLists]-->b.     <!--[endif]-->int ival = ival;

<!--[if !supportLists]-->c.     <!--[endif]-->int ival(int());

<!--[if !supportLists]-->d.     <!--[endif]-->double salary = wage = 999.99;

解释:两项有问题:D wage没声明;A auto是关键字

B是可以但是会有warning;C可以他会初始化ival为整形的默认值

 

<!--[if !supportLists]-->3.     <!--[endif]-->下面那些定义合法:       

<!--[if !supportLists]-->a.     <!--[endif]-->long* const cpl;

<!--[if !supportLists]-->b.     <!--[endif]-->const long lc;

<!--[if !supportLists]-->c.     <!--[endif]-->const long* const cplc;

<!--[if !supportLists]-->d.     <!--[endif]-->const long* plc;

解释:选d,abc因为作为一个常量,必须在声明的时候初始化。而d是一个指针,它指向一个常长整形,可以不初始化,a是指向长整形的常量指针;b是常长整形;c是常长整形的常量指针。

 

<!--[if !supportLists]-->4.     <!--[endif]-->已知有如下定义:

long l = 10;

const long cl = 100;

那么下面表达式不正确的是:     

<!--[if !supportLists]-->a.     <!--[endif]-->const long* pl = &cl;

<!--[if !supportLists]-->b.     <!--[endif]-->long* const pl = &cl;

<!--[if !supportLists]-->c.     <!--[endif]-->const long* const pl = &cl;

<!--[if !supportLists]-->d.     <!--[endif]-->const long* pl = &l;

B

A常长整形的指针pl指向常长整形cl

B长整形的常量指针pl指向了常长整形,pl能指向的东西是长整形,不是常长整形

C常长整形的常量指针指向常长整形

D常长整形的指针pl指向一个长整形,可以,可以从long形变化到const long形

D和B类似,但是B错的原因是不能从const long转化成long

 

<!--[if !supportLists]-->5.     <!--[endif]-->已知: long lVal = 5; 下面那些定义无效:    c  

<!--[if !supportLists]-->a.     <!--[endif]-->long& lRef = lVal;

<!--[if !supportLists]-->b.     <!--[endif]-->const long& lRef = 5;

<!--[if !supportLists]-->c.     <!--[endif]-->long& lRef = 5;

<!--[if !supportLists]-->d.     <!--[endif]-->const long& lRef = lVal;

解释:C

C错是因为5这个数字算是一个常量,但是long& 类型的lRef不能引用

原因同上题不能从一个const long 转换为一个long

 

<!--[if !supportLists]-->6.     <!--[endif]-->下面的函数定义不构成重载的是:       

a.  long hoo( long m, long n = 0 );

long hoo( const long m );

 

b.  long hoo( long m );

long hoo( const long m );

 

c.  long hoo( const long m );

double hoo( const long m);

 

d.  long hoo( long m = 0, long n = 0 );

long hoo( long m = 0 );

解释:C

返回值类型不同是不能构成重载的!

这里特别要注意d!如果调用的是hoo()或者hoo(100)会造成二义性!因为有了默认参数编译器并不知道哪个更合适!

 

<!--[if !supportLists]-->7.     <!--[endif]-->已知模板函数的定义

template <class T1, class T2, class T3>

T1 sum( T2, T3 );

变量定义:

    double dobj1, dobj2;

    float   fobj1, fobj2;

    char    cobj1, cobj2;

下面哪一个调用是错误的:      

<!--[if !supportLists]-->a.     <!--[endif]-->sum( dobj1, dobj2 )  ;

<!--[if !supportLists]-->b.     <!--[endif]-->sum<double, double, double>( fobj1, fobj2 );

<!--[if !supportLists]-->c.     <!--[endif]-->sum<int>( cobj1, cobj2 );

<!--[if !supportLists]-->d.     <!--[endif]-->sum<double, int, char>( cobj1, cobj2 );

解释:a

原因是编译器无法推演出T1的类型,a选项里没有写明T1的类型,而sum函数需要T1的类型去特化出一个函数能够处理dobj1和dobj2这两个参数的函数。其他的都可以。

 

<!--[if !supportLists]-->8.     <!--[endif]-->下面的throw表达式中, 哪一个是错误的:       

<!--[if !supportLists]-->a.     <!--[endif]-->class exception{};

throw exception;

<!--[if !supportLists]-->b.     <!--[endif]-->long excpobj;

throw excpobj;

<!--[if !supportLists]-->c.     <!--[endif]-->enum MathError{ overflow, underflow, zerodivide };

throw overflow;

<!--[if !supportLists]-->d.     <!--[endif]-->long excpobj = 0;

long* pl = &excpobj;

throw *pl;

解释:

可以抛出任何类型,但是必须是某类型的对象,A中抛出的是一个类型,不对!

 

<!--[if !supportLists]-->9.     <!--[endif]-->现有类定义如下:

class X

{

public:

    X();

    ~X();

private:

    long m_lID;

};

下面的表达式中, 没有调用到类X的构造函数的是:    

<!--[if !supportLists]-->a.     <!--[endif]-->X x;

<!--[if !supportLists]-->b.     <!--[endif]-->foo( X()); ( foo原型为 void foo( X& ); )

<!--[if !supportLists]-->c.     <!--[endif]-->X y = x; (x是a中的定义)

<!--[if !supportLists]-->d.     <!--[endif]-->X* pax = new X[10];

解释:c

C用的是复制构造函数。其函数原型载这个题中并没写出来,是默认的

如X(const X& object){…}

 

<!--[if !supportLists]-->10.  <!--[endif]-->类X的定义同第8题, 下面的表达式中, 没有调用到类X的析构函数的是:       

<!--[if !supportLists]-->a.     <!--[endif]-->{ X x; }

<!--[if !supportLists]-->b.     <!--[endif]-->X* px = new X; delete px;

<!--[if !supportLists]-->c.     <!--[endif]-->X* pax = new X[10]; delete pax;

<!--[if !supportLists]-->d.     <!--[endif]-->{ X* px = new X; }

解释:d在一个作用域里用这种new方式分配内存的对象,必须手动delete才会释放内存,否则不会自动调用析构函数,会造成内存的泄漏

C是错误的应该是delete[] pax;因为分配了很多对象,如果像c中那么写只能调用一次析构函数,也会造成内存泄漏

 

<!--[if !supportLists]-->11.  <!--[endif]-->下面的表达式中, 编译将能通过的是:       

<!--[if !supportLists]-->a.     <!--[endif]-->#include <vector>

vector<long> vectlCount;

<!--[if !supportLists]-->b.     <!--[endif]-->#include <vector.h>

vector<long> vectlCount;

<!--[if !supportLists]-->c.     <!--[endif]-->#include <vector>

std::vector<long> vectlCount;

<!--[if !supportLists]-->d.     <!--[endif]-->#include <vector.h>

std::vector<long> vectlCount;

选c

在C++中,vector这样的头文件须写成#include <vector>这样,而不能加.h;而且它在std命名空间中,要使用必须加std::前缀,或者using namespace std;对于标准库里的所有组件都是这样的道理。

 

<!--[if !supportLists]-->12.  <!--[endif]-->下面哪句话是正确的:       

<!--[if !supportLists]-->a.     <!--[endif]-->一个class必须供应至少一个constructor.

<!--[if !supportLists]-->b.     <!--[endif]-->所谓的default constructor 是指其参数列表中没有参数.//不需要用户输入,参数列表里可以定义变量并初始化等。

<!--[if !supportLists]-->c.     <!--[endif]-->一个class对象被构造时, 不一定就会调用其constructor.

<!--[if !supportLists]-->d.     <!--[endif]-->如果class定义中不显示供应一个default constructor, 则编译器会自动生成一个, 用以为每个data member设定默认值.

解释:

A至少有一个,没有写出来,编译器会自动添加一个

b默认构造函数不是这个意思~

C可以调用复制构造函数copy constructor

D默认构造函数在有别的构造函数的时候不会在由编译器生成

 

<!--[if !supportLists]-->13.  <!--[endif]-->已知下面的基类和子类,

class CBase

{

public:

    char foo( int );

protected:

    int m_bar;

    double m_foo_bar;

};

class CDerived : public CBase

{

public:

    char foo( string );

    bool bar( CBase* pb );

    void foobar();0

protected:

    string m_bar;

};

下面的代码, 正确的是:       

<!--[if !supportLists]-->a.     <!--[endif]-->CDerived d; d.foo( 1024 );

<!--[if !supportLists]-->b.     <!--[endif]-->void CDerived::foobar() { m_bar = 1024; }//warning, truncation from 'const int' to 'char'。

<!--[if !supportLists]-->c.     <!--[endif]-->bool CDerived::bar( CBase* pb )

{ return m_foo_bar == pb->m_foo_bar; }//不能调用父类的protected对象m_foo_bar

<!--[if !supportLists]-->d.     <!--[endif]-->void CDerived::foobar(){ CBase::m_foo_bar = 2048; }

解释:D

A没有这样的函数!子类的同名函数会覆盖父类的同名实现

B会出一个warning:warning,truncation from 'const int' to 'char'。但其实用的时候就会出错,因为编译器是不知道m_bar是哪个的!

Cpb不能直接调用m_foo_bar 是protected

D可以这么用,不过直接写就可以了

 

<!--[if !supportLists]-->14.  <!--[endif]-->子类Derived继承基类Base, 则下面的子类对于基类的 “虚函数override中”哪个是正确的(下面基类的函数都是virtual的):       

<!--[if !supportLists]-->a.     <!--[endif]-->Base* Base::copy( Base* );

Base* Derived::copy( Derived* );

<!--[if !supportLists]-->b.     <!--[endif]-->Base* Base::copy( Base* );

Derived* Derived::copy( Base* );

<!--[if !supportLists]-->c.     <!--[endif]-->ostream& Base::print( int, ostream& = cout );

ostream& Derived::print( int, ostream& );

<!--[if !supportLists]-->d.     <!--[endif]-->void Base::eval() const;

void Derived::eval();

解释:

d如果是同一个类型两个函数重名一个为const一个不是,那么是重载,如果是两个类型里,应该是不算重写的。

 

<!--[if !supportLists]-->15.  <!--[endif]-->有如下声明:

class CAD { }; class Vehicle { };

class CADVehicle : public CAD, Vehicle { };

请问类CADVehicle 是以什么方式继承类Vehicle的:       

<!--[if !supportLists]-->a.     <!--[endif]-->public 方式//

<!--[if !supportLists]-->b.     <!--[endif]-->protected 方式

<!--[if !supportLists]-->c.     <!--[endif]-->private 方式

<!--[if !supportLists]-->d.     <!--[endif]-->因为 Vehicle前面没有指定修饰符, 所以上述写法是错误的.//

解释:路过的朋友,如果知道这个题的正确答案,麻烦给我留个言。

B这个题是我试出来的,不过是vc6下调试的,感觉是c

 

<!--[if !supportLists]-->16.  <!--[endif]-->已知如下的类层次结构. 其中每一个类都定义了一个default constructor和一个virtual destructor:

class X { };

class A { };

class B : public A { };

class C : public B { };

class D : public X, public C { };

下面哪一个dynamic_cast 会失败:       

<!--[if !supportLists]-->a.     <!--[endif]-->D* pd = new D;

A* pa = dynamic_cast<A*>( pd );

<!--[if !supportLists]-->b.     <!--[endif]-->A* pa = new C;

C* pc = dynamic_cast<C*>( pa );

<!--[if !supportLists]-->c.     <!--[endif]-->B* pb = new B;

D* pd = dynamic_cast<D*>( pb );

<!--[if !supportLists]-->d.     <!--[endif]-->A* pa = new D;

X* px = dynamic_cast<X*>( pa );

解释:C

因为pb自西那个的是B类型,B类型不是D类型,所以不能转换


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值