【问题标题】:Constructor invocation issue构造函数调用问题
【发布时间】:2018-02-13 07:18:51
【问题描述】:

在此代码中尝试创建 dobj4 时出现编译器错误

#include<iostream>
using namespace std;
class mod;
class  name {
    friend mod;
    public:
            name(const char* n) {
                    cout << "1 arg constructor for name\n";
            }
            name() {
                    cout << "no arg constructor for name\n";
            }
            name(const char* n, int i ){
                    cout << "2 arg constructor for name\n";
            }
      };

class mod {
    public:
    mod() {
            cout << "base class constructor invoked\n";
    }
};

struct derived : mod {

    derived(name) {
            cout << "derived constructor invoked\n";
    }
 };

int main() {
    name nobj;
    derived dobj(nobj);

    name nobj1("hello");
    derived dobj1(nobj1);

    derived dobj2("Hi");

    name nobj2("yo", 2);
    derived dobj3(nobj2);

 //      derived dobj4("go", 4);

    return 0;
}

需要了解在 dobj2 的情况下传递字符串时如何调用名称的构造函数,但在 dobj4 的情况下会导致错误。 如何解决这个问题?

【问题讨论】:

  • 构造函数不会自动继承。
  • 派生的没有可以接受两个参数的构造函数。在派生中添加一个构造函数为 derived(const char *n, int n) { // impelmentation }。它应该可以工作。
  • 我怀疑你误解了参数的隐式转换是如何工作的。在您最喜欢的 C++ 书籍中阅读更多有关它的信息。
  • 是的 c++ 新手,我试图了解转换是如何在 dobj2 中发生的,但不是在 dobj4 中,感谢支持
  • @ashkun 我认为您需要澄清您的问题。即使有了 molbdnilo 的评论,也花了一些时间来理解您的问题

标签: c++ c++11 c++14 c++builder


【解决方案1】:

我觉得你的问题可能会更短更容易理解示例代码:(我还修复了它以使其可编译)

即使继承在这里没有相关性,我也留下了派生名称,并且我已将其删除为不重要

#include<iostream>
class  name {
public:
    name() {
        std::cout << "no arg constructor for name\n";
    }
    name(const char* n) {
        std::cout << "1 arg(" << n <<") constructor for name\n";
    }
    name(const char* n, int i ) {
        std::cout << "2 arg(" << n << ',' << i <<") constructor for name\n";
    }
};
struct derived {

    derived(const name& n ) {
        std::cout << "derived name constructor invoked\n";
        (void)n;
    }
};

int main() {

    name nobj;
    derived dobj(nobj);

    derived dobj2("Hi");

    derived dobj4({"go", 4}); //see the initialization list instead of 2 parameters passing

    return 0;
}

【讨论】:

    【解决方案2】:

    C++03C++11 的构造函数转换规则各不相同。

    C++03 中:只有一个参数的构造函数,或者在有多个参数的情况下,其余参数具有默认值 是隐式可转换的。

    例子:

    name(const char* n) {}
    name(int n, int i = 0) {} // i has a default value
    

    C++11:上面C++03 中定义的所有情况以及具有多个参数的构造函数。但是这样的构造函数调用需要大括号初始化

    例子:

    derived dobj4({"go", 4}); // call to name(const char* n, int i) is brace-initialized
    

    不用说,如果构造函数被声明为explicit,它就不会被转换。

    【讨论】:

    • 我想你的意思是说构造函数是一个“转换构造函数”,如果它满足那些参数条件的话。但这与问题无关,只是术语
    • 是的,没有默认参数。仍然不确定你想说什么。
    • 使用 C++11 标志,它应该使用大括号初始化构造,即使有多个参数除了第一个之外没有默认值。我的示例中的第一行编译(带有({})),第二行只有{} 没有。
    • 哦,我明白了。但是上面代码中的默认参数使构造函数可能不明确。这让我分心了。
    • 啊。对我来说是个坏例子。改正了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多