【问题标题】:Initialize a const class member with a default value使用默认值初始化 const 类成员
【发布时间】:2016-06-22 21:25:48
【问题描述】:

我有两个课程ABbclass 类型为 B 是类 A 的常量成员;如果没有向A 提供B 对象,我想要做的是用默认值初始化类bclass。 像这样的:

#include <iostream>
#include <string>
#include <unistd.h>

using namespace std;

class B{
public:
  B(string Bs): Bstring(Bs){
    cout << "B constructor: " << Bstring << endl;
  }

  ~B(){
    cout << "B destructor: " << Bstring << endl;
  }

private:
  const string Bstring;
};

class A{
public:
  A(const B subb = B("mmmmm")): bclass(subb){
    cout << "A constructor." << endl;
  }

  ~A(){
    cout << "A destructor." << endl;
  }

private:
  const B bclass;
};

int main(void){
    A a;
    cout << "doing work..." << endl;
    sleep(2);
    return 0;
}

输出是:

B constructor: mmmmm
A constructor.
B destructor: mmmmm
doing work...
A destructor.
B destructor: mmmmm

问题是我正在构建 2 个 B 类(?),而只需要一个! 而且不知何故,B构造函数只被调用了一次,而析构函数被调用了两次......这是怎么回事?!

编辑 1:

在阅读了@WhiZTiM 的(很棒的)回复后,我添加了接下来的两个更新...

下面的代码解释了何时调用第二个构造函数:

#include <iostream>
#include <string>
#include <unistd.h>

using namespace std;

class B{
public:
  B(string Bs): Bstring(Bs){
    cout << "B constructor: " << Bstring << endl;
  }
  B(const B& bobj): Bstring(bobj.Bstring + "(copy)"){
    cout << "B copy constructor: " << Bstring << endl;
  }

  ~B(){
    cout << "B destructor: " << Bstring << endl;
  }

private:
  const string Bstring;
};

class A{
public:
  A(const B& subb = B("mmmmm")): bobj(subb){
    cout << "A constructor." << endl;
  }

  ~A(){
    cout << "A destructor." << endl;
  }

private:
  const B bobj;
};

int main(void){
  A a;
  cout << "doing work..." << endl;
  sleep(2);
  return 0;
}

输出:

B constructor: mmmmm
B copy constructor: mmmmm(copy)
A constructor.
B destructor: mmmmm
doing work...
A destructor.
B destructor: mmmmm(copy)

正如@WhiZTiM 指出的那样,编译器忽略了对 B 构造函数的第三次调用(谢谢!)。

编辑 2: 因为我只想要 1 B 对象,所以最好的办法是使用指针。代码必须是:

#include <iostream>
#include <string>
#include <unistd.h>

using namespace std;

class B{
public:
  B(const string Bs): Bstring(Bs){
    cout << "B constructor: " << Bstring << endl;
  }
  B(const B& bobj): Bstring(bobj.Bstring){
    cout << "copying an existing B object." << endl;
  }

  ~B(){
    cout << "B destructor: " << Bstring << endl;
  }

private:
  const string Bstring;
};

class A{
public:
  A(B* subb = new B("mmmmm")): objb(subb){
    cout << "A constructor." << endl;
  }

  ~A(){
    cout << "A destructor." << endl;
    delete objb;
  }

private:
  const B* const objb;
};

int main(void){
  A a1; // This will call the default B constructor.
  A a2(new B("ooooo"));// This is calling a non default B object constructor.
  cout << "doing work..." << endl;
  sleep(2); //I need more motivation...
  return 0;
}

这是输出:

B constructor: mmmmm
A constructor.
B constructor: ooooo
A constructor.
doing work...
A destructor.
B destructor: ooooo
A destructor.
B destructor: mmmmm

非常感谢@WhiZTiM

【问题讨论】:

  • B 不是常量子类。 AB 的复合对象
  • 首选A(const B&amp; subb = B("mmmmm"))A(const B subb = B(...)) 是一个非常糟糕的主意,因为你不能 move 一个 const 对象......或者更好的是 pass-by-value A(B subb = B("mmmmm"))

标签: c++ constructor constants


【解决方案1】:

问题是我正在构建 2 个 B 类(?),而只有一个是 需要!不知何故,B构造函数只被调用一次,而 析构函数被调用了两次......这是怎么回事?!

没有魔法发生。编译器生成隐式复制和移动构造函数。 要获得真实的图片,请实施您的


class A{
public:
  A(const B subb = B("mmmmm")): bclass(subb){
    cout << "A constructor." << endl;
  }

  ~A(){
    cout << "A destructor." << endl;
  }

private:
  const B bclass;
};

在您的构造函数中,B 是使用单参数构造函数创建的,然后分配给 subb,然后将其复制到 bclass... 所以实际上创建了 3 个 B 实例。

  • 第一个是您的用户定义构造函数,这就是您看到输出的原因
  • 第二个是用于构造subb的move构造函数-编译器生成默认
  • 第三个是用于构造bclass的复制构造函数--编译器生成默认

您可能已经看到了 2,因为编译器 elided a call

【讨论】:

  • 感谢您的回答。你为我清除了很多东西。现在,如果我只需要构建一个 B 对象,您有什么建议?
  • 我改了A类。现在 'bclass' 是 'const B* bclass;'并将 'A' 构造函数更改为 'A(B* subb = new B("mmmmm")): bclass(subb){' 效果很好!
猜你喜欢
  • 2019-09-10
  • 1970-01-01
  • 1970-01-01
  • 2015-03-22
  • 1970-01-01
  • 2012-08-29
  • 1970-01-01
  • 2011-08-09
  • 2015-10-09
相关资源
最近更新 更多