有一个类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
假定一个类的构造函数为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
下列关于构造函数的描述正确的是?
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
假定有类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
若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
如果MyClass为一个类,执行”MyClass a[5], *b[6]
”语言会自动调用该类构造函数的次数是()
A. 2 B. 5
C. 4 D. 9
此时实例化一个数组对象a,数组中有5个MyClass元素,所以调用5次构造函数,b是一个指针数组,内含6个MyClass类型的指针,没有实例化对象,所以不调用构造函数。
答案选:B
下面对析构函数的正确描述是()
A. 系统不能提供默认的析构函数
B. 析构函数必须由用户定义
C. 析构函数没有参数
D. 析构函数可以设置默认参数
析构函数的概念:析构函数
与构造函数功能相反,析构函数不是完成对对象本身的销毁,局部对象销毁工作是由编译器完成的。而对象在销毁时会自动调用析构函数,完成对象中资源的清理工作。
析构函数有以下特点:
(1)析构函数名是在类名前加上字符 ~。
(2)无参数无返回值类型。
(3)一个类只能有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。
(4)析构函数不能重载。
(5)对象生命周期结束时,C++编译系统系统自动调用析构函数。
(6)如果类中没有申请资源时,析构函数可以不写,直接使用编译器生成的默认析构函数,比如Date类;有资源申请时,一定要写,否则会造成资源泄漏,比如Stack类。
所有对于选项A,B,当我们没有写析构函数的时候,系统会提供一个默认的析构函数,析构函数没有参数,不能重载,所以一个类只能有一个析构函数,D错误。
答案选:C
哪种说法是错误的()?
A. 构造函数可以有形参
B. 析构函数可以有形参
C. 构造函数无任何函数类型
D. 析构函数无任何函数类型
构造函数可以有形参实现重载,但是一个类只能有一个析构函数,所以析构函数没有形参。构造函数和析构函数都没有返回值。
答案选:B
在 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
两种排序方法
解题思路:
我们将接受的字符串都放到vector容器中,利用string的operator>=运算符重载来按ascii比较字符串,利用string的size来比较字符串的长度。
#include
#include
#include
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;
}
求最小公倍数
解题思路:
最小公倍数 = 两数之积除以最大公约数,这里使用碾转相除法进行最大公约数的求解:即a与b的最大公约数可以转化为a、b之间的余数为两者之间最小的数之间的公约数。所以对于输入的两个数进行连续求余,直到余数为0,求余的分母即为结果。
#include
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;
}