1. 假设有如下一个类
class String{
public:
String(const char *value);
~String();
char* strcpy(char* dest, const char* source);
size t strlen( const char *string );
…
private:
char *data;
};
要求利用类中的已知函数实现该类的赋值运算符“operator=”。
String& String::operator=(const String& rhs)
答案:
String& String::operator=(const String& rhs)
{
if(this == &rhs) return *this; // 检查对自己赋值的情况
delete [ ] data; // delete old memory
//分配新内存,将rhs 的值拷贝给它
data = new char[strlen(rhs.data)+1];
strcpy(data, rhs.data);
return *this; //返回
}
2. 假设Complex是一个类。请问以下两种实现方式在效率上可能有什么区别?为什
么?
方式1:
Complex a, b, c, d, result;
…
result = a + b + c + d;
方式2:
Complex a, b, c, d, result;
…
result += a;
result += b;
result += c;
result += d;
答案:
方式2的效率有可能比方式1要高一些。因为方式1运算中要产生三个临时对象, 如
果该类的构造复杂,那么会浪费较多时间。而一般情况下,方式2可以不用产生任
何临时对象。
3. 判断下列每行代码是否正确,错误的请解释原因。
( a ) int ival = 1.01; ( k ) int i = -1;
(b) int &rval1 = 1.01; ( l ) const int ic = i;
( c ) int &rval2 = ival; (m) const int *pic = &ic
(d) int &rval3 = &ival (n) int *const cpi = &ic
( e ) int *pi = &ival ( o ) const int const* cpic = &ic
( f ) int &rval4 = pi; (p) pic = cpic;
( g ) int &rval5 = *pi; ( q ) cpic = &ic
(h) int &*prval1 = pi; ( r ) cpi = pic;
( i ) const int &ival2 = 1; ( s ) ic = *cpic;
( j ) const int &*prval2 = &ival ( t ) pic = &ic
答案:
(a) 正确;
(b) 错误,必须是一个const引用才正确改为:const int &rval1 = 1.01;
(c) 正确;
(d) 错误,rval3的类型是int而非int *,改为int &rval3 = ival; 或者int* const &rval3
= &ival
(e) 正确;
( f ) 错误,rval4的类是int而非int *,改为int * &rval4 =pi;
(g) 正确;
(h) 错误,指向引用的指针是不合法的,改为int *&prval1 = pi;
( i ) 正确;
( j ) 错误,指向引用的指针是不合法的,改为int * const & prval2 = &ival
(k) 正确;
( l ) 正确;
(m) 正确;
(n) 错误,cpi是一个常量指针,指向int,但是ic却是一个const int;
(o) 正确,cpic是一个常量指针,指向const int, ic的类型也是const;
(p) 正确;
(q) 正确;
(r) 错误,cpi是个常量,不能被修改;
(s) 错误,ic是个常量,不能被修改;
(t) 正确。
4. 阅读下面的程序段,写出运行结果。
class A{
public:
A() { printf(“A 构造!n”); }
virtual ~A(){printf(“A 析构!n”); }
virtual output1(){ printf( “output A1!n” );}
virtual output2() { printf( “output A2!n” ); }
};
class B : public A{
public:
B() { printf(“B 构造!n”);}
virtual ~B(){ printf(“B 析构!n”);}
virtual output1(){ printf( “output B1!n ” ); }
};
class C : public B{
public:
C(){ printf(“C 构造!n”);}
virtual ~C() { printf(“C 析构!n”);}
virtual output1() { printf( “output C1!n ” );}
};
int main()
{
C ObjC;
ObjC.output1();
ObjC.output2();
}
答案:
A 构造!
B 构造!
C 构造!
output C1 !
output A2 !
C 析构!
B 析构!
A 析构!
5. 阅读下面的程序段,写出运行结果。请说明理由。
#include
using namespace std;
class Base {
public:
virtual double f(double i){
cout << " Here in the class Base, f(int): ";
return i+1;
}
};
class Derived : public Base{
public:
double f(double d){
cout << " Here in the class Derived, f(double): ";
return d+1.1;
}
};
int main()
{
Base* derived = new Base;
cout << derived->f(10) << 'n';
cout << derived->f(10.1) << 'n';
}
答案:
Here in the class Derived, f(double): 11.1
Here in the class Derived, f(double): 11.2
理由:C++语言中无法在派生类中进行重载,所以两个函数调用均调用派生类中
的函数。
6. 阅读下面的程序段,写出运行结果。请说明理由。
#include
#include
using namespace std;
int main(){
string s1(“Nancy”);
string s2(“Clancy”);
string& rs = s1;
string *ps = &s1
rs = s2;
cout<
{
public:
namedptr(const string& initname, t *initptr){name = initname; ptr = initptr;}
private:
const string& name;
t * const ptr;
};
答案: 这个类的定义要求使用一个成员初始化列表,因为const成员只能被初始
化,不能被赋值。
9. (编程题)验证歌德巴赫猜想:任一充分大的偶数,可以用两个素数之和表示。
例如:
4 = 2 + 2
6 = 3 + 3
…
98 = 19 + 79
答案:
#include
using namespace std;
bool IsPrime(int nPrime);
int main(int argc, char* argv[])
{
int nEven = 0;
cout <<"Please input an even number (N >= 4)!” << endl;
cout << "If you want to exit this program, please input 0." << endl << endl;
cout <<"N = ";
cin >> nEven;
while(nEven != 0) //0 to exit
{
bool bSuccess = false;
while (nEven < 4) //too small
{
cout << "Sorry, please input a number no less than 4!" << endl;
cout << "N = ";
cin >> nEven;
if(nEven == 0) //exit
{
cout <<"Exit!" << endl;
return 0;
}
}
while((nEven % 2) == 1)//not an even number
{
cout <<"Sorry, please input an even number (N >= 4)!” << endl;
cout << "N = ";
cin >> nEven;
if(nEven == 0) //exit
{
cout <<"Exit!" << endl;
return 0;
}
}
for(int i = 2; i <= nEven/2; i++)
{
if( IsPrime(i) && IsPrime(nEven - i) ) //prime number
{
cout << nEven <<" = " << i <<" + " << nEven-i << endl;
cout << "N = ";
cin >> nEven;
bSuccess = true;
break;
}
}
if (!bSuccess) //is that possible?
{
cout << endl <<"God!" << endl;
cout << "The Goldbach Conjecture is Wrong!" << endl;
cout <<"Exit!" << endl;
return 0;
}
}
cout << "Exit!" << endl;
return 0;
}
bool IsPrime(int nPrime) //Is a number Prime?
{
if(nPrime == 2 || nPrime == 3)
return true;
for(int i = 2; i <= int(sqrt((double)nPrime) + 0.5); i++)
if(nPrime % i == 0)
return false; //no, it isn't a prime number
return true; //yes, it is a prime number.
}
10. (编程题)设有一个背包可以放入的物品的重量为s,现有n件物品,重量分别
为w[1];w[2]; … ;w[n]。问能否从这n件物品中选择若干件放入此背包中, 使得放
入的重量之和正好为s。如果存在一种符合上诉要求的选择,则称此背包问题有解
(或称其解为真);否则称此背包问题无解(或称其解为假)。试用的递归方法
设计求解背包问题的算法。(提示:此背包问题的递归定义可分四种情况来考虑:
1) s = 0; 2) s < 0; 3) s > 0 and n < 1; 4) s > 0 and n>=1.)
答案:
KNAP(s,n) 有以下四种情况:
True s = 0
False s < 0
False s > 0 and n < 1
KNAP(s, n- 1) or KNAP(s- w[n], n- 1) s > 0 and n >= 1
#include
#include
bool KNAP(int s,int n, int *w,int &rnum)
{
bool ret,ret1;
if(s == 0)
return true;
else if(s < 0)
return false;
else if(s > 0 && n <= 0)
return false;
else if(s > 0 && n > 0)
{
int snew;
int wnew[100]; //用来保存新的数据
int i, j, k=0;
for(i=0; i
{
int len = rnum;
for(j=0; j
cout <<"Input the number of the goods: "<
if(num <= 0) {
printf("the number of the goods must be greater than 0!n");
return 0;
}
w = new int[num];
int i = 0;
while(i < num) {
printf("Input the weight of the %d th goods:", i);
cin>>w[ i ];
if(w[ i ] < 0)
printf("the weight of the %d th goods must be great/equal 0!n", i);
else
i++;
}
int len=0;
bool ret = KNAP(s,num,w, len);
if(!ret)
printf("There is no solution!n");
else
printf("There is a solution!n");
delete [ ]w;
return 0;
}