文章目录
- 【类和对象】
- 1. 构造、拷贝构造的调用
- 2. 静态成员变量
- 3. 初始化列表
- 4. 成员函数:运算符重载
- 5. 友元函数、友元类
- 55. 特殊类设计
- 【细节题】
- 1. 构造 析构 + new \ deletet、new[] \ delete[]
【类和对象】
1. 构造、拷贝构造的调用
#include
using namespace std;
class MyClass{
public:
MyClass(int i=0){cout<<1;}
MyClass(const MyClass&x){cout<<2;}
MyClass& operator=(const MyClass&x){cout<<3; return*this;}
~MyClass(){cout<<4;}
};
int main(){
MyClass obj1(1),obj2(2),obj3(obj1);
return 0;
}如上程序,运行时的输出结果是()
A. 121,444
B. 112,444 √
C. 11,114,444
D. 11,314,445
E. 11,314,444
2. 静态成员变量
下列静态数据成员的特性中,错误的是()
A. 引用静态数据成员时,要在静态数据成员名前加<类名>和作用域符号
B. 说明静态数据成员时前边要加关键字static来修饰
C. 静态数据成员在类体外进行初始化
D. 静态数据成员不是所有对象所共有的 ×
-
静态成员变量:
-
- 所有对象共享的,并不属于具体的某个对象
-
- 定义和声明方式:在类中声明,然后需要在类外单独进行定义,一定不能在构造函数初始化列表的位置初始化(有一个例外,const static,紧接在后面说明)
-
- 类外访问:
对象.静态成员变量
or类名::静态成员变量
- 类外访问:
下面有关c++静态数据成员,说法正确的是()
A. 不能在类内初始化
B. 不能被类的对象调用
C. 不能受private修饰符的作用
D. 可以直接用类名调用 √
// const static 的成员变量是可以在类中定义的
class A
{
private:
const static int a = 10; // 编译通过
//static int b = 20; // err..编译报错
static int b;
};
A::b = 20; // 普通的静态成员变量这样写才行
3. 初始化列表
有一个类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
- 初始化列表只能对类中 非静态 的成员变量进行初始化。
- 初始化列表种才是真的初始化,在构造函数的函数体中的是赋值。
-
三种 必须要在初始化列表中初始化 的成员变量:
- const 成员变量
- 引用 成员变量
- 自定义类型 成员(且该类 没有默认构造函数,即 没有无参的构造函数 时)
4. 成员函数:运算符重载
在重载一个运算符为成员函数时,其参数表中没有任何参数,这说明该运算符是 ( )。
A. 无操作数的运算符
B. 二元运算符
C. 前缀一元运算符 √
D. 后缀一元运算符
解析: 每个非静态的成员函数都有一个隐藏的 this 指针。前缀和后缀的举例如下。
// 前缀 ++
Date& operator++()
// 后缀 ++
Date& operator++(int)
补充代码:
C++ 中,有如下类模板定义:
template class BigNumber{
long n;
public:
BigNumber(T i) :n(i) {}
BigNumber operator+(BigNumber b) {
return BigNumber(n + b.n);
}
};已知 b1, b2 是 BigNumber 的两个对象,则下列表达式中错误的是()
A. 3+3
B. b1+3
C. b1+b2
D. 3+b1 ×
- 成员函数的第一个参数其实是 隐藏的 this 指针。
- 如果类中有 单个参数 的构造函数,该构造函数具有 类型转换 的作用。
解析:
A. 是一个普通的加号连接两个整型的表达式,正确。
B. 首先,第一个参数为 this 指针类型的 BigNumber 对象,满足。其次,BigNumber 类中有单参数构造函数,而 3 恰好是整型可以作为构造函数的参数,编译器在编译代码时,会调用但参构造函数将 3 转化为 BigNumber 的对象。两个对象相加,正确。
C. 标准的两个对象相加,正确。
D. 由于隐藏的 this 指针的存在要求 + 号前面的操作数,是 BigNumber 类型的对象,3 不满足,故错误。
5. 友元函数、友元类
下面有关友元函数与成员函数的区别,描述错误的是?
A. 友元函数可以让本类和友元类对象调用
B. 友元函数和类的成员函数都可以访问类的私有成员变量或者是成员函数
C. 类的成员函数是属于类的,调用的时候是通过指针this调用的
D. 友元函数是有关键字friend修饰,调用的时候也是通过指针this调用的 ×
友元函数:不是类的成员函数,更不会有 this 指针,但是在友元函数中可以访问类中私有的成员。
成员函数:具有隐藏的 this 指针,受访问限定符的约束,通过对象来调用
55. 特殊类设计
在C++中,为了让某个类只能通过new来创建(即如果直接创建对象,编译器将报错),应该()
A. 将构造函数设为私有
B. 将析构函数设为私有 √
C. 将构造函数和析构函数均设为私有
D. 没有办法能做到
经典特殊类总结:
-
只能创建一个对象的类(单例模式:饿汉模式和懒汉模式)
- 饿汉模式:利用 静态成员变量,一开始(在 main 函数之前) 就创建对象
- 懒汉模式:类在 第一次访问 实例对象 时创建 不能被拷贝的类
-
=delete
拷贝构造函数 以及 赋值运算符重载
只能在堆上创建对象的类
- 思路1: 析构 函数设成私有,普通对象就不给创建了,同时建立一个公共函数包装析构函数,需要析构的时候显示调用该函数。
- 思路2: 构造 函数设成私有,并提供一个在堆上创建对象的接口,还需要 delete 掉拷贝和赋值。(不推荐) 只能在栈上创建对象的类
- 构造 函数设为私有,并提供一个在栈上创建对象的接口 不能被继承的类
- C++98: 构造 函数设成私有
-
C++11:
final
【细节题】
1. 构造 析构 + new \ deletet、new[] \ delete[]
ClassA *pclassa=new ClassA[5];
delete pclassa;C++语言中,类ClassA的构造函数和析构函数的执行次数分别为()
A. 5,1 √
B. 1,1
C. 5,5
D. 1,5
解析:本题使用的 new[],并没有配合 delete[] 使用,而是使用了 delete。也就是 new 了 5 个数据,只析构了 1 个。不过,这是错误的使用方法,很可能导致内存泄漏等问题。
-
三种堆上申请内存的方法:
-
- malloc/calloc/realloc—>free
-
- new / delete
-
- new[] / delete[]
- 一定要匹配起来使用,否则程序可能会产生内存泄漏或者程序可能会崩溃