繁体   English   中英

为什么要尝试调用默认构造函数?

[英]Why is this attempting to call the default constructor?

在我的原始项目中,我有一个类,该类的构造函数应该在构造类成员之前调用初始化函数。 但是,编译器给我一个错误,提示缺少类成员的默认构造函数。

class One
{
public:
    One(int i) {};
};

class Two
{
    One one;

public:
    Two() {one(0)};
};

int main(void)
{
    Two two;
}

编译器给我这个:

Problem.cpp: In constructor ‘Two::Two()’:
Problem.cpp:12:15: error: no matching function for call to ‘One::One()’
         Two() {one(0)};
           ^
Problem.cpp:4:9: note: candidate: ‘One::One(int)’
         One(int i) {};
         ^~~
Problem.cpp:4:9: note:   candidate expects 1 argument, 0 provided
Problem.cpp:1:7: note: candidate: ‘constexpr One::One(const One&)’
 class One
       ^~~
Problem.cpp:1:7: note:   candidate expects 1 argument, 0 provided
Problem.cpp:1:7: note: candidate: ‘constexpr One::One(One&&)’
Problem.cpp:1:7: note:   candidate expects 1 argument, 0 provided
Problem.cpp:12:21: error: no match for call to ‘(One) (int)’
         Two() {one(0)};

为什么此代码尝试为Two构造函数中的One调用默认构造函数,以及如何产生预期的行为(构造函数中其他初始化代码之后的构造成员)?

如何产生预期的行为(在构造函数中其他初始化代码之后的构造成员)?

这是不可能的。 在C ++中,必须在输入构造函数的主体之前构造所有对象的基类和非静态成员变量。

在您的代码中,您编写了Two构造函数的开头{ ,而之前没有为该成员变量提供任何构造函数参数,因此该成员变量是默认构造的。


如果你有一些逻辑来制定出初始化one ,那么我会建议把该进的功能:

int f() { /* logic here */ return 0; }

// ...

Two(): one( f() ) {}

当然,您也可以向One添加默认构造函数,以及以后分配给它的方法。

之所以调用默认构造函数,是因为您不调用将int作为参数的构造函数。 您必须在初始化列表中执行以下操作:

class Two
{
    One one;

public:
    Two() : one(0) {}
};

您还需要正确声明变量:

Two two;

Two two();

通过添加一个init函数并使用逗号运算符,您可以摆脱这种情况:

class Two
{
    One one;

    void init()
    {
        // Initialize things here
    }

public:
    Two() : one((init(), 0)) {}
};

首先,调用init() ,然后将0传递给One构造函数。

你需要这个:

class One
{
public:
    One(int i) {};
};

class Two
{
    One one;

public:
    Two() : one(0) {};
};

int main(void)
{
    Two two();
}

之所以调用One的默认构造函数,是因为需要在Two::Two构造函数的第一行代码之前构造Two::one ,否则还没有真正构造Two 通过将One构造函数调用放置在初始化程序列表中,可以确保One在运行任何未初始化的Two代码之前获取它需要构造的参数。

该错误是因为在进入Two()构造函数的主体之前,必须完全构造Two的所有成员,但是您没有在Two()构造函数的成员初始化列表中显式构造one成员,因此编译器将尝试默认构造您的one成员,由于One类没有默认构造函数而失败。

要执行您的要求,您需要:

  • 使One可以默认构造,并在需要时给它一种分配新值的方法:

     class One { private: int value; public: One(int i = 0) : value(i) {} One& operator=(int rhs) { value = rhs; return *this; } }; class Two { private: One one; // <-- default constructed! public: Two() { // initialization as needed... one = 0; // <-- reassignment afterwards } }; 
  • one成员更改为一个One*指针,然后您可以随时构造它,例如:

     class One { private: int value; public: One(int i = 0) : value(i) {} One(const One &src) : value(src.value) {} }; class Two { private: One *one; public: Two() : one(NULL) { // initialization as needed... one = new One(0); } // don't forget about the "Rule of 3"... Two(const Two &src) : one(NULL) { // initialization as needed... one = new One(*(src.one)); } ~Two() { delete one; } Two& operator=(const Two &rhs) { if (&rhs != this) { Two temp(rhs); std::swap(one, temp.one); } return *this; } }; 

    或者,如果您使用的是C ++ 11或更高版本:

     #include <memory> class Two { private: std::unique_ptr<One> one; public: Two() { // initialization as needed... one.reset(new One(0)); // or: in C++14 and later: // one = std::make_unique<One>(0); } // don't forget about the "Rule of 3"... Two(const Two &src) { // initialization as needed... one.reset(new One(*(src.one))); // or: in C++14 and later: // one = std::make_unique<One>(*(src.one)); } Two& operator=(const Two &rhs) { if (&rhs != this) { Two temp(rhs); std::swap(one, temp.one); } return *this; } // and the "Rule of 5"... Two(Two &&src) { // initialization as needed... one = std::move(src.one); } Two& operator=(Two &&rhs) { one = std::move(rhs.one); return *this; } }; 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM