Ссылка как инициализация члена класса

Я хочу инициализировать свойство класса, которое содержит ссылку на другой класс, передавая такую ​​ссылку как параметр конструктору. Однако я получаю сообщение об ошибке:

"TaxSquare:: bank" должен быть инициализирован в списке конструкторов base/member initializer". Что не так в следующем коде классов?

#ifndef TAXSQUARE_H
#define TAXSQUARE_H
#include "Square.h"

class Bank;

class TaxSquare : public Square
{
    public:
      TaxSquare(int, int, Bank&);
      virtual void process();

    private:
      int taxAmount;
      Bank& bank;

};
#endif
#include <iostream>
#include "TaxSquare.h"
#include "Player.h"
#include "Bank.h"
using namespace std;

TaxSquare::TaxSquare(int anID, int amount, Bank& theBank) : Square(anID)
{
  taxAmount = amount;
  bank = theBank;
}
#ifndef BANK_H
#define BANK_H

class Bank
{
public:
  Bank(int, int, int);
  void getMoney(int);
  void giveMoney(int);
  void grantHouse();
  void grantHotel();

private:
  int sumMoney;
  int numOfHouses;
  int numOfHotels;

};

#endif

Ответы

Ответ 1

Вы пытаетесь назначить bank, а не инициализировать его:

TaxSquare::TaxSquare(int anID, int amount, Bank& theBank) : Square(anID)
{
    // These are assignments
    taxAmount = amount;
    bank = theBank;
}

bank является ссылкой, и поэтому он должен быть инициализирован. Вы делаете это, поместив его в список инициализаторов:

TaxSquare::TaxSquare(int anID, int amount, Bank& theBank)
: Square(anID), taxAmount(amount), bank(theBank)
{}

Ответ 2

Ошибка, которую вы пытаетесь назначить с помощью неинициализированной ссылки: ссылка С++ не может быть назначена - вместо нее назначается объект, к которому он относится, - и поэтому, если это член, он должен быть инициализирован в списке инициализаторов ( как говорит компилятор).

Ответ 3

"TaxSquare:: bank" должен быть инициализирован в списке конструкторов base/member initializer". Что не так в следующем коде классов?

Неправильно то, что TaxSquare::bank не инициализируется в списке инициализации base/member конструктора, точно так, как он говорит.

"Список инициализации основы/члена конструктора" является списком инициализации для рассматриваемого конструктора, TaxSquare::TaxSquare(int, int, Bank&). Вы уже используете его для инициализации базы (Square). Вы должны использовать его для инициализации члена bank, потому что он имеет ссылочный тип. Вещи, не указанные в списке инициализации, инициализируются по умолчанию, и для ссылок нет инициализации по умолчанию, потому что они всегда должны ссылаться на что-то, и для них не существует никакого значения по умолчанию.

Честно говоря, я считаю, что использование ссылок для членов данных в С++ - это больше проблем, чем стоит 99% времени. Вы, вероятно, лучше со смарт-указателем или даже с сырым. Но вы должны по-прежнему инициализировать это с помощью списка инициализации, даже если вы можете уйти без него. То же самое касается taxAmount, действительно.

// TaxSquare::TaxSquare(int anID, int amount, Bank& theBank) : Square(anID)
// That thing after the colon is the initialization list:      ^^^^^^^^^^^^
// So add the other members to it, and then notice that there is nothing left
// for the constructor body to do:
TaxSquare::TaxSquare(int anID, int amount, Bank& theBank) : 
Square(anID), taxAmount(amount), bank(theBank) {}

Ответ 4

bank = theBank; это утверждение означает, что вы назначаете obj1 obj2, и он вызывает оператор присваивания, который неверен, поскольку банк имеет тип ссылки, он должен быть проиндексирован, как указано ниже.

TaxSquare:: TaxSquare (int anID, int amount, Bank & theBank): Square (anID), bank (theBank) {}