C++ Q&A(六)构造函数的常见问题

声明:Q&A系列的文章是我在平时自己遇到的或者看到的一些问题,本着再小的问题也需要有人解答的想法,将这些问题和答案整理出来。

欢迎和我讨论问题,同时也欢迎转载Q&A系列的文章。


前两篇文章说了new运算符的有些相关知识,现在我们再来探讨一下有关C++的构造函数的问题。下面的问题都是在面试中很 经常被问到的。


1.构造函数可以是虚吗?

我在面CVTE的二面的时候就被问了这个问题。首先先放上结论:不可以。原因有两个:

a)虚函数也只是一个函数,调用虚函数的时候,我们需要的只是这个虚函数的接口信息就可以了。但是调用构造函数就需要这个类的完整信息,包括类的大小等等。是不是有点矛盾。你可能会说,那我有类的全部信息一样可以调用虚函数啊?那请看第二个原因。

b)C++的虚机制是通过虚函数表实现的,拥有虚函数的类都有一个指向虚函数表的指针(vptr),而这个vptr是在构造期间被赋值的,那么问题来了,如果类还没构造起来起来,怎么找到类的虚函数呢?明显是不可以的。


2.虚函数可以有返回值吗?

这个同样也是CVTE的二面问题。结论:不可以。

用代码来解释一下吧。如果虚函数有返回值,就有这样的歧义:

class A {
public :
    int A() { return 0; };
};
那么下面一个语句构造的是什么类型:

pa = new A();
那pa是什么类型?int还是A的指针?这就存在歧义的。

往深入的层面说,构造函数是一个回调函数,没有返回值的。


3.什么时候需要复制构造函数?

这个在C++Primer中有说到,下面内容摘自C++ Primer第五版:

拷贝初始化不仅在我们使用=定义变量时会发生,在下列情况下也会发生:

1.将一个对象作为实参传递给非引用类型的形参

2.从一个返回类型为非引用类型的函数返回一个对象

3.用花括号列表初始化一个数组中的元素或一个聚合类中的成员


4.什么时候需要将一个类的构造函数声明为explicit?

将一个类的构造函数声明声明为explicit是为了防止隐式转换的发生。举个例子:

<span style="font-size:10px;">#include <stdio.h>
#include <stdlib.h>
class A {
public :
  A(int i) { _i = i; }
  const A operator += (const A &rhs) {
    _i += rhs._i;
    return *this;
  }
  int i() const { return _i; }
private :
  int _i;
};
int main() {
  A a(10);
  printf("%d\n", a.i());
  a += 10;
  printf("%d\n", a.i());
  return 0;
}</span>
因为A的构造函数没有被声明为explicit,因此,int到A类型的隐式转换就发生了。那么什么会发生因此其他类型到类类型的隐式转换呢?

1.类似上面的例子,当类的构造函数只有一个单一参数的时候

2.当一个类的构造函数有多个参数,但是至多只有一个没有默认参数。例如:A(int i, double d1 = 0.0, double d2 = 1.2);这也会发生隐式转换

为了避免这种隐式转换的发生,只需要在类的构造函数前面加上explicit关键字就可以了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值