【问题标题】:c++ Using overloaded constructor on object compositionc ++在对象组合上使用重载构造函数
【发布时间】:2013-11-10 05:27:03
【问题描述】:

我可以知道如何在另一个类中使用重载的构造函数进行对象组合,这是一个示例代码:

class A {
    int a;

    A( int inputA ) { a = inputA; }
};

class B {
    A objectA;

    B( A inputObjectA ) { objectA = inputObjectA; }
};

编译器的错误是没有默认构造函数 A::A() ?

有没有办法编辑B的构造函数的参数中的代码来接受A中重载的构造函数?

【问题讨论】:

  • 使用构造函数初始化列表。

标签: c++ constructor-overloading


【解决方案1】:

如果子节点没有默认构造函数,则父节点的构造函数应该传递参数。

class A {
public:
    int a;
    A( int inputA ) { a = inputA; }
};

class B {
    A objectA;
public:
    B( A inputObjectA ): objectA(inputObjectA.a) { }
};

http://ideone.com/QavhfY

在您的情况下,最好为 A 使用复制构造函数,而不是将其成员公开:

class A {
    int a;
public:
    A( int inputA ) { a = inputA; }
};

class B {
    A objectA;
public:
    B(A inputObjectA ): objectA(inputObjectA) { }
};

http://ideone.com/wX1clr

【讨论】:

  • 嗨,为了让您的解决方案正常工作,我必须在 A 类中有一个默认构造函数,对吗?所以不管我需要一个默认构造函数吗?如果没有,B( A inputObjectA ): objectA(inputObjectA) { } 将触发未找到默认构造函数
  • 我的解决方案中没有 A 的默认构造函数。不,不会有编译器错误。我添加了指向 ideone 的链接,以证明代码可以正常编译。
  • 感谢您的解释,但是我的案例研究需要 B 接受 A 类对象而不引用。
  • 我已删除参考。它们只是有助于避免额外的副本。
  • 糟糕,A(A that) 构造函数被 C++11 拒绝:(
【解决方案2】:

在你的 B 类对象中

A objectA;

这是调用默认构造函数的时候,所以你需要有一个指定的默认构造函数,或者你可以选择使用默认参数,例如

A( int inputA = 0 ) { a = inputA; }

这将起到将整数a设置为0的作用,当你调用默认构造函数时,它真的会达到同样的效果

A() { a = 0; } 

虽然 如果您不想设置,则不必设置,但由于您声明了一个非默认构造函数,它不再为您隐式创建一个。所以你至少需要

A(){ }  

另一种方法是

class A {
    int a;
    void setSomething(int val) { a = val; }
};

class B {
    A objectA;
    B( A inputObjectA ) { objectA = inputObjectA; }
};

这是因为你从未声明任何构造函数,所以它会隐式地为你创建一个默认构造函数

最后,这是您可以做到的另一种方式,可能最接近您的原始代码,只添加了 3 个字符,应该可以解决所有问题:

class A {
    int a;

    A( int inputA ) { a = inputA; }
};

class B {
    A objectA(0);

    B( A inputObjectA ) { objectA = inputObjectA; }
};

【讨论】:

  • 有什么办法可以编辑B的构造函数的参数中的代码来接受A中重载的构造函数。
  • 此外,当您为类定义构造函数时,不再调用默认构造函数
  • 错误不是来自那里,它来自A ObjectA所以这一行应该改变
【解决方案3】:

只需将A() 的参数传递给B() 的构造函数即可。 此解决方案适用于A,它既不是默认可构造的,也不是复制或移动可构造/可分配的。

class A 
{
    int a;

    // Just to demonstrate non copy-move-ness (can be removed)
    A() = delete;
    A( A& ) = delete;
    A( A&& ) = delete;
    A& operator=( A& ) = delete;
    A& operator=( A&& ) = delete;
public:
    A( int inputA ): a(inputA ) {}
};

class B 
{
    A objectA;
public:
    B( int inputA ): objectA(inputA ) { }
};


int main() 
{
    B(42);
}

Proof

提示:不要在构造函数主体中使用赋值,而是使用构造函数初始化列表。

您可以从any modern C++ book 获得所有这些信息。

【讨论】:

    【解决方案4】:

    你需要一个默认构造函数,因为你在类 B 中有一个类 A 的实例。如果你阅读了一些关于构造函数调用顺序的内容,你会注意到首先调用成员的默认构造函数,然后然后是主类构造函数。所以 - 在你的例子中 - 首先编译器尝试使用默认值初始化 objectA,但它失败了,因为没有默认构造函数。

    【讨论】:

    • 在这种情况下,有一种方法可以将参数传递给非默认构造函数。应该修改 B 构造函数来这样做。看我的回答。
    • 错了。即使成员是按值的,默认构造函数也没有绝对必要。
    • 虽然你们说的都是对的,但在我提供答案时,问题的内容却有所不同。用户没有问“如何改变预兆”,而是“我需要一个默认构造函数”。因此,虽然更改代码以使用初始化列表是一个好主意,但对原始问题的回答是“是的,您需要它,因为...”。
    猜你喜欢
    • 2013-07-09
    • 1970-01-01
    • 2011-07-30
    • 2021-07-12
    • 2010-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多