【C/C++笔试练习】初始化列表、构造函数、析构函数、两种排序方法、求最小公倍数

C/C++笔试练习

1. 初始化列表

(1)只能在列表初始化的变量

  有一个类A,其数据成员如下:

class A {
...
private:
	int a;
public:
	const int b;
	float* &c;
	static const char* d;
	static double* e;
};

  则构造函数中,成员变量一定要通过初始化列表来初始化的是:______。

  A. a b c     B. b c
  C. b c d e     D. b c d
  E. b      F. c

  
  初始化列表是什么:

  以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每个"成员变量"后面跟一个放在括号中的初始值或表达式。

  初始化列表的示例:

class Date
{
public:
Date(int year, int month, int day)
	: _year(year)
	, _month(month)
	, _day(day)
{}
 
private:
	int _year;
	int _month;
	int _day;
};

  初始化列表注意的地方:

  (1)每个成员变量在初始化列表中只能出现一次(初始化只能初始化一次)

  (2)类中包含以下成员,必须放在初始化列表位置进行初始化:

      1.引用成员变量

      2.const成员变量

      3.自定义类型成员(且该类没有默认构造函数时)

  (3)尽量使用初始化列表初始化, 因为不管你是否使用初始化列表,对于自定义类型成员变量,一定会先使用初始化列表初始化。

  (4)成员变量在类中声明次序就是其在初始化列表中的初始化顺序, 与其在初始化列表中的先后次序无关。

  只能在初始化列表中初始化的类型示例:

class A
{
public:
	A(int a)
	:_a(a)
	{}

private:
	int _a;
};

class B
{
public:
B(int a, int ref)
	:_aobj(a)
	,_ref(ref)
	,_n(10)
	{}
	
private:
	A _aobj; // 没有默认构造函数
	int& _ref; // 引用
	const int _n; // const 
};

  
  根据上面的内容,我们知道const修饰的成员变量和引用成员变量只能使用初始化列表来进行初始化,a是内置成员可以在初始化列表也可以在函数体内初始化,而静态成员变量d,e只能在类外进行定义,不能在初始化列表中进行初始化, 所以选择b,c。

   答案选:B

            

2.构造函数

(2)函数体赋值

  假定一个类的构造函数为A(int aa,int bb){a=aa--;b=a*bb;}则执行A x(4,5);语句后,x.a和x.b的值分别为()

   A. 20和5      B. 3和15
   C. 5和4        D. 4和20

  在创建对象时,编译器通过调用构造函数,给对象中各个成员变量一个合适的初始值

class Date
{
public:
Date(int year, int month, int day)
{
	_year = year;
	_month = month;
	_day = day;
}
private:
	int _year;
	int _month;
	int _day;
};

  函数体赋值和初始化列表不同:

  虽然上述构造函数调用之后,对象中已经有了一个初始值,但是不能将其称为对对象中成员变量的初始化,构造函数体中的语句只能将其称为赋初值,而不能称作初始化。因为初始化只能初始化一次,而构造函数体内可以多次赋值。

  
在这里插入图片描述
  

  在上面的程序中,先实例化了A对象x(4,5),将4,5分别赋值给A构造函数中的,aa和bb,然后函数体内赋值,注意:这里先把aa=4赋值给a,然后才执行后置–,此时,a=4,aa=3;然后b=a*bb,计算得到b=20, 输出即可。

   答案选:D

  

(3)构造函数的概念

   下列关于构造函数的描述正确的是?

   A. 构造函数可以声明返回类型     B. 构造函数不可以用private修饰
   C. 构造函数必须与类名相同      D. 构造函数不能带参数

  

  构造函数的介绍:构造函数

  构造函数是C++中的一个特殊函数,用于初始化类对象的数据成员,为对象分配内存并完成一些初始化工作。一个类可以有多个构造函数,但必须满足函数名相同、参数列表不同的条件,称为函数重载。

  构造函数有以下特点:

  (1)构造函数的函数名与类名相同。

  (2)构造函数无返回值。

  (3)对象实例化时编译器自动调用对应的构造函数。

  (4)构造函数可以重载。

  (5)如果一个类没有定义自己的构造函数,编译器会自动生成一个默认的构造函数,该函数不带任何参数并且什么也不做,它会自动初始化类的成员变量并分配内存。一旦用户显式定义编译器将不再生成

  (6)C++把类型分成内置类型(基本类型)和自定义类型。内置类型就是语言提供的数据类型,如:int/char…,自定义类型就是我们使用class/struct/union等自己定义的类型,编译器生成默认的构造函数会对自定类型成员_t调用的它的默认成员函数。

  (7)无参的构造函数和全缺省的构造函数都称为默认构造函数,并且默认构造函数只能有一个。注意:无参构造函数、全缺省构造函数、我们没写编译器默认生成的构造函数,都可以认为是默认构造函数。

  

  根据上面对构造函数的简单介绍,对于a构造函数没有返回值,b构造函数可以在实现特殊类的时候就有使用private修饰,c构造函数和类名相同,构造函数可以重载带参数。

   答案选:C

  

(4)构造函数调用次数

  假定有类AB,有相应的构造函数定义,能正确执行语句,请问执行完此语句后共调用该类的构造函数次数为___

AB a(4),b(5),c[3],*p[2]={&a,&b}

  A. 5     B. 4
  C. 3     D. 9

  
在这里插入图片描述
  
  开始的时候我们实例化了a,b,这里会调用两次的单参数构造,然后实例化一个数组c,c中有三个元素,所以会调用三次默认构造,注意,这里的p是一个指针数组,创建的是指针,没有实例化对象。

  所以,总共调用了2 + 3 = 5次构造函数。因此,答案为A. 5。

   答案选:A

  

(5)构造函数调用次数

  若MyClass是一个类名,其有如下语句序列:

MyClass c1,*c2;
MyClass *c3=new MyClass;
MyClass &c4=c1;

  上面的语句序列调用构造函数个数是( )。

  A. 1      B. 2
  C. 3      D. 4

  
在这里插入图片描述

  
  和上面类似,实例化c1,调用一次构造函数,c2是指针,不调用构造函数,c3指向一个MyClass对象,此时再实例化一个Myclass对象,调用一次构造函数,c4是c1的引用,不调用构造函数。

   答案选:B

  

(6)构造函数调用次数

  如果MyClass为一个类,执行”MyClass a[5], *b[6]”语言会自动调用该类构造函数的次数是()

  A. 2     B. 5
  C. 4     D. 9

在这里插入图片描述
  
  此时实例化一个数组对象a,数组中有5个MyClass元素,所以调用5次构造函数,b是一个指针数组,内含6个MyClass类型的指针,没有实例化对象,所以不调用构造函数。

   答案选:B

            

3.析构函数

(7)析构函数的概念

  下面对析构函数的正确描述是()

  A. 系统不能提供默认的析构函数
  B. 析构函数必须由用户定义
  C. 析构函数没有参数
  D. 析构函数可以设置默认参数

  
  析构函数的概念:析构函数

  与构造函数功能相反,析构函数不是完成对对象本身的销毁,局部对象销毁工作是由编译器完成的。而对象在销毁时会自动调用析构函数,完成对象中资源的清理工作。

  析构函数有以下特点:

  (1)析构函数名是在类名前加上字符 ~。

  (2)无参数无返回值类型。

  (3)一个类只能有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。

  (4)析构函数不能重载。

  (5)对象生命周期结束时,C++编译系统系统自动调用析构函数。

  (6)如果类中没有申请资源时,析构函数可以不写,直接使用编译器生成的默认析构函数,比如Date类;有资源申请时,一定要写,否则会造成资源泄漏,比如Stack类。

  
   所有对于选项A,B,当我们没有写析构函数的时候,系统会提供一个默认的析构函数,析构函数没有参数,不能重载,所以一个类只能有一个析构函数,D错误。

   答案选:C

  

(8)析构函数的概念

   哪种说法是错误的()?

   A. 构造函数可以有形参
   B. 析构函数可以有形参
   C. 构造函数无任何函数类型
   D. 析构函数无任何函数类型

  
   构造函数可以有形参实现重载,但是一个类只能有一个析构函数,所以析构函数没有形参。构造函数和析构函数都没有返回值。

   答案选:B

  

(9)构造和析构的顺序

  在 main 函数中,变量 a 和 b 的构造函数和析构函数的调用顺序是()

class A;
class B;
int main() {
	A a;
	B b;
	return 0;
}

  A. b构造 - a构造 - a析构 - b析构
  B. a构造 - a析构 - b构造 - b析构
  C. b构造 - a构造 - b析构 - a析构
  D. a构造 - b构造 - b析构 - a析构

  
   我们先实例化A类的对象a,此时a会调用构造函数,然后类B的对象b会被构造。要注意,这里的操作和new和delete的底层相似,当main函数结束时,对象b会被首先析构,然后是对象a。 所以,整个生命周期的顺序应该是:a构造 - b构造 - b析构 - a析构。

   答案选:D

            

4.编程题 day8

(10)两种排序方法

两种排序方法

  解题思路:

  我们将接受的字符串都放到vector容器中,利用string的operator>=运算符重载来按ascii比较字符串,利用string的size来比较字符串的长度。

#include<iostream>
#include<vector>
#include<string>
using namespace std;

int main()
{
	int n;
	cin>>n;
	vector<string> v;
	v.resize(n);
	for(auto& str : v)
	cin>>str;
	bool lenSym = true, lexSym = true;
	
	// 这里要注意从i=1开始遍历,前后比较,比较长度
	for(size_t i = 1; i < v.size(); ++i)
	{
		if(v[i-1].size() >= v[i].size())
		{
			lenSym = false;
			break;
		}
	}
	
	//比较ASCII码
	for(size_t i = 1; i < v.size(); ++i)
	{
		if(v[i-1] >= v[i])
		{
			lexSym = false;
			break;
		}
	}
	
	if (lenSym&& lexSym)
		cout<<"both"<<endl;
	else if (!lenSym && lexSym)
		cout<<"lexicographically"<<endl;
	else if (lenSym && !lexSym)
		cout<<"lengths"<<endl;
	else if (!lenSym&&!lexSym)
		cout<<"none"<<endl;
		
	return 0;
}

  

(11)求最小公倍数

求最小公倍数

  解题思路:

  最小公倍数 = 两数之积除以最大公约数,这里使用碾转相除法进行最大公约数的求解:即a与b的最大公约数可以转化为a、b之间的余数为两者之间最小的数之间的公约数。所以对于输入的两个数进行连续求余,直到余数为0,求余的分母即为结果。

#include<iostream>
using namespace std;

int gcd(int a, int b)
{
	int r;
	while(r = a%b)
	{
		a = b;
		b = r;
	}
	return b;
}

int main()
{
	int a,b;
	while(cin >> a >> b)
	{
		cout << a*b/gcd(a,b) <<endl;
	}
	return 0;
}
  • 9
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 16
    评论
评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

鳄鱼麻薯球

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值