【问题标题】:Constructor parameters C++ const and &构造函数参数 C++ const 和 &
【发布时间】:2018-02-21 17:08:14
【问题描述】:

我无法正确获取构造函数的参数。它一遍又一遍地弹出相同的错误。类的参数不能改,只能改构造函数。

错误 C2789 'Aluno::numero':必须初始化 const 限定类型的对象

错误 C2530 'Aluno::escola':必须初始化引用

class Aluno {
    string nome;
    string& escola;
    const int numero;
public:
    Aluno(string nome, string escola, int numero){
        this->nome = nome;
        this->escola = escola;
        this->numero = numero;
    }
};

int main()
{
    Aluno * a = new Aluno("aaa", "bbb", 123);

    return 0;
}

【问题讨论】:

  • 为什么escola 是参考?通常,您会在构造函数初始化器列表中初始化它们,但如果您不能更改构造函数的参数 - 充其量只能绑定到局部变量,这会在尝试使用它时导致 UB。跨度>
  • 谷歌“成员初始化列表”。
  • @SergeyA 如果您觉得我的回答不好,我欢迎对我的回答提出建设性的批评。
  • @JesperJuhl 我看不出它如何回答 OP 问题。诚然,OP 的问题可能无法回答,但应该避免回答。

标签: c++ class constructor


【解决方案1】:

const 或引用的类成员必须在构造函数的成员初始化列表中初始化,例如:

class Aluno
{
    string nome;
    string& escola;
    const int numero;
public:
    Aluno(string nome, string &escola, int numero)
        : nome(nome), escola(escola), numero(numero)
    {
    }
};

int main()
{
    string b = "bbb";
    Aluno * a = new Aluno("aaa", b, 123);
    delete a; 
    return 0;
}

但是,请注意我必须更改您的 escola 输入参数。您正在传递该参数按值,但正在尝试存储对它的引用。 escola 类成员将绑定到构造函数本地的 string 对象,并在构造函数退出时超出范围,从而使引用悬空。你不想这样。

因此,escola 输入参数也必须更改为引用,如上所示,否则 escola 类成员不能再声明为引用,例如:

class Aluno
{
    string nome;
    string escola;
    const int numero;
public:
    Aluno(string nome, string escola, int numero)
        : nome(nome), escola(escola), numero(numero)
    {
    }
};

int main()
{
    Aluno * a = new Aluno("aaa", "bbb", 123);
    delete a; 
    return 0;
}

【讨论】:

  • 这将涉及更改构造函数参数:OP 声明不允许这样做。
  • @AlgirdasPreidžius 我知道,但是这个要求没有意义,它会导致未定义的行为,所以必须改变一些东西。
  • “必须在构造函数的成员初始化列表中初始化” - 不完全正确。使用default member initializer 也可以。
【解决方案2】:

对于const 成员,您需要使用初始化列表:

Aluno(string nome, string escola, int numero)
    : numero(numero) {
    // ...
}

您还需要以相同的方式初始化引用,但这需要将引用作为参数传递:

Aluno(string nome, string& escola, int numero)
    : escola(escola), numero(numero) {
    // ...
}

即使编译器不需要它,以同样的方式初始化nome 效率更高。

Aluno(string nome, string& escola, int numero)
    : nome(nome), escola(escola), numero(numero) {
}

【讨论】:

  • 这将导致 UB,在使用 escola 时,因为它是一个悬空引用。
  • UB 兜售的另一个例子。
  • 编辑后,这并不能修复 OP 得到的编译器错误。
  • @AlgirdasPreidžius 您提到的编辑修复了第一个编译器错误。我最近的编辑应该解决另一个错误。
  • @Code-Apprentice 但是,OP 声明他们不能更改构造函数参数。
【解决方案3】:

初始化 成员,您需要使用类内初始化或构造函数初始化列表。 不是构造函数体。

在构造函数主体中,您可以为成员重新分配值,但此时它们已经被默认初始化(除非您在类中显式初始化它们或使用初始化列表)并且并非所有类型都可以默认初始化(如参考)。

【讨论】:

    【解决方案4】:

    escola 是一个引用,因此在分配时需要在字段初始化列表中对其进行初始化。您的 const numero 也是如此:

    Aluno(string nome, string escola, int numero) : 
        nome(nome), escola(escola), numero(numero) { }
    

    但是,这将导致 UB,因为您的成员 escola 引用的参数 escola 将超出范围。因此,参数也必须是引用:

    Aluno(string nome, string &escola, int numero) : 
        nome(nome), escola(escola), numero(numero) { }
    

    【讨论】:

    • 但它指的是什么
    • 这将导致 UB,在使用 escola 时,因为它是一个悬空引用。
    • 这将修复编译错误(可能),但会是 UB。
    • @scohe001 OP 声明他们无法更改构造函数参数。
    • @AlgirdasPreidžius 我认为 OP 指的是班级成员
    猜你喜欢
    • 1970-01-01
    • 2013-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-10
    • 1970-01-01
    • 1970-01-01
    • 2016-01-02
    相关资源
    最近更新 更多