BerthaDusStuf Ответов: 3

Я не понимаю этого в конструкторах классов


В книге, которую я читаю "прыжки в C++", есть некоторые вещи, которые я не понимаю. Вот этот код:

class ChessBoard
{
public:
ChessBoard ();
string getMove ();
ChessPiece getPiece (int x, int y);
void makeMove (int from_x, int from_y, int to_x, int to_y);
private:
PlayerColor _board[ 8 ][ 8 ];
string _whose_move;
};


Это было все объявление класса но затем вот реализация конструктора:

ChessBoard::ChessBoard ()
// the colon is followed by the list of variables, with the argument
// to the constructor
: _whose_move( "white" )
{
// at this point, _whose_move constructor has been called and it
// contains the value "white"
}


Во-первых, парень помещает "белый" в конструктор whose_move. Какой в этом смысл так как чей ход это струна так что вы можете просто сделать:

строка whose_move = "белый"

Во-вторых, whose_move объявляется вне скобок функции, почему?

Что я уже пробовал:

____________________________________________-

3 Ответов

Рейтинг:
28

Afzaal Ahmad Zeeshan

Поскольку конструктор не работает таким образом в C++, конструкторы вызываются сразу после создания объекта (или уже были созданы). Это означает, что код в теле должен выполняться после создания объекта, просто для целей проверки или около того.

В C++ вы можете инициализировать объект таким образом, поэтому, когда он это сделал,

ChessBoard::ChessBoard ()
// the colon is followed by the list of variables, with the argument
// to the constructor
: _whose_move( "white" )
{
// at this point, _whose_move constructor has been called and it
// contains the value "white"
}

Он инициализировал поле в момент создания объекта, скорее после этого. А whose_move-это в основном строка, и опять же, в C++ вы можете легко создавать такие переменные, как,
string _whose_move = "white";
string _whose_move("white");

// I know pointers involved here
string _whose_move = new string("white");

Это все зависит от того, что вы хотите сделать, и как вы хотите написать программу, попробуйте этот пример кода, который я написал для вас; Оболочка C++ [^], он записывает мое имя, код выглядит следующим образом,
// Example program
#include <iostream>
#include <string>

int main()
{
  std::string name("Afzaal Ahmad Zeeshan");
  std::string name2 = "Afzaal Ahmad Zeeshan";
  std::string* nameRef = new std::string("Afzaal Ahmad Zeeshan");
  std::cout << "Hello, " << name << " from the constructor-like!\n" << std::endl;
  std::cout << "Hello, " << name2 << " from the variable!\n" << std::endl;
  std::cout << "Hello, " << *nameRef << " from the pointer!\n" << std::endl;
}

При этом у нас есть три способа записи переменной, которые вы можете проверить сами. Теперь возьмите эту концепцию обратно в конструктор C++ и добавьте смесь синтаксической поддержки C++, вы можете легко увидеть, какие из них могут быть поддержаны в этом домене.

А теперь смотри вот это,
class person {
public:
    std::string name;  
    person(std::string);
};

person::person(std::string n) : name(n) {
    std::cout << "Person created with name " << n  << "." << std::endl;
}

Попробуйте сделать это,
person::person(std::string n) : name = n {

Он начинает жаловаться, и так далее, и тому подобное. Итак, дело в том, что вы должны следовать стандартам C++ и синтаксису, иначе возникают проблемы. Серьезные.

Окончательная программа для вас, чтобы опробовать и протестировать; Оболочка C++ [^]


BerthaDusStuf

Хорошо, но в чем разница между передачей "белого" в конструктор и установкой строки равной белому при ее объявлении?

Afzaal Ahmad Zeeshan

Пожалуйста, перечитайте ответ, разница в том, что один делается до того, как объект будет инициализирован, а другой-просто как функция сеттера.

BerthaDusStuf

да, я читал ваш ответ довольно много, но я изо всех сил пытаюсь понять, что вы имеете в виду.
Например здесь:
- Он инициализировал поле во время создания объекта, а не после этого."
мой вопрос заключается в том, что хорошо бы не делать строку whose_move = "white" также инициализировать поле во время создания объекта?

Afzaal Ahmad Zeeshan

Я понимаю, что концепции немного отличаются в C++, и с C++ это сложнее, чем вы можете себе представить, с Java или C# это гораздо проще. Но в C++ существует концепция RAII (выделение ресурсов-это инициализация). Это означает, что при выделении ресурса он инициализируется, скорее наоборот — инициализируется позже, как вы говорите, с помощью string name = "something";

Так что в других терминах,

// Notice we are not passing anything
ChessBoard::ChessBoard () : _whose_move()
{
}

это похоже на то, что мы имеем с

ChessBoard::ChessBoard ()
{
}
Компилятор неявно инициализирует строковые переменные значениями по умолчанию, а передача белого цвета означает, что значением по умолчанию для них будет белый цвет.

Пожалуйста, смотрите следующие ссылки для получения немного более подробных объяснений по этой теме,
https://www.quora.com/In-C++-why-are-class-members-initialized-with-their-default-constructor-before-the-constructor-body-executes-instead-of-the-compiler-detecting-which-members-werent-initialized-during-the-constructor-and-initializing-them-with-the-default-constructor-afterwards#
https://stackoverflow.com/questions/9903248/initializing-fields-in-constructor-initializer-list-vs-constructor-body

BerthaDusStuf

хорошо спасибо

Рейтинг:
2

KarstenK

Решение правильное, потому что он помещал строку в конструктор о струне В противном случае был бы выполнен стандартный конструктор, который вводит компилятор на этапе сборки.

Представьте себе это как:

ChessBoard::ChessBoard() : _whose_move()
{
}
Подсказка: все остальные члены класса тоже.

Для установки строки вам нужен некоторый код, который не является оптимальным:
ChessBoard::ChessBoard()
{
 _whose_move = "white";
}
Вы можете доказать это, войдя в код конструктора с отладчиком, когда шахматная доска будет построена. :-О


BerthaDusStuf

извините я не очень хорошо понимаю

Рейтинг:
2

CPallini

До C++17 список инициализаторов был правильным способом инициализации членов класса со значениями по умолчанию. С C++17 инициализацию по умолчанию можно обеспечить непосредственно в теле класса. Попробуйте, с современным компилятором

#include <iostream>
using namespace std;

class ChessBoard
{
public:
  ChessBoard (){}
  string getMove ();
  void makeMove (int from_x, int from_y, int to_x, int to_y);
  void showWhoseMove(){ cout << _whose_move << "\n"; }
private:
  string _whose_move = "white"; // allowed only since C++17
};

int main()
{
  ChessBoard cb{};
  cb.showWhoseMove();
}


Nelek

Тег-это C++11 ;)

BerthaDusStuf

хорошо спасибо