简体   繁体   中英

Calling non-empty constructor when defining a member object within a header file

I feel like this is a mere syntactical question, but I can't find a unique/succinct way to describe it so Google isn't helping.

Here is a code snippet to see what I am talking about. The part that is preventing compilation is pointed out in a comment.

Deck.h:

#include <random>
#include <iostream>

class Deck{
    int top;
    int cards[52];

    public:
     Deck();
     void shuffle();

    private:
        // the "(0,51)" on the following line is a syntax error
        // without it, compilation is fine
        std::uniform_int_distribution<int> distribution(0,51);
        std::shuffle_order_engine<std::default_random_engine, 52> engine;
};

Deck.cpp:

#include "Deck.h"
#include <random>
#include <algorithm>

Deck::Deck(){}

void Deck::shuffle(){
    top = 0;
    int oldCards[52];
    std::copy_n(cards, 52, oldCards);
    for(int i = 0; i < 52; i++){
        int random = distribution(engine);
        std::cout << "random= " << random << std::endl;
        cards[i] = oldCards[random];
    }
}

I need to have the uniform_int_distribution instantiated with the range 0 to 51 to shuffle the deck. I could declare it as a pointer and allocate it dynamically, but this seems like it shouldn't be necessary.

Coming from experience in C, I am trying to learn to write good, idiomatic C++ code, so anything else you can point out is appreciated. Of course, the actual working of the shuffling will be debugged once I can get compilation.

Thank you for any answers.

You can use curly braces, or copy initialization syntax.

Alternatively you can initialize that member in each constructor's member init list.

For C++03 the latter is the only possibility.


Curly braces:

std::uniform_int_distribution<int> distribution{ 0, 51 };

Copy initialization syntax (only available if the type is copyable or movable):

std::uniform_int_distribution<int> distribution =
    std::uniform_int_distribution<int>( 0, 51 );

Initialization in constructor member init list:

Deck::Deck()
    : distribution( 0, 51 )
{}

C++11 supports both parenthesis and braces when initializing members in a class declaration, eg:

class Deck
{
    ...   
    private:
        std::uniform_int_distribution<int> distribution(0,51);
        ...
};

class Deck
{
    ...   
    private:
        std::uniform_int_distribution<int> distribution{0,51};
        ...
};

For non-C++11 compilers, you have to use the initializer list of the containing class's constructor to provide values to class member constructors (a C++11 compiler silently translates the above code into this logic behind the scenes), eg:

class Deck
{
    ...   
    private:
        std::uniform_int_distribution<int> distribution; // <-- DO NOT try to invoke the constructor here!
        ...
};

Deck::Deck()
  : distribution(0,51) <-- invoke the constructor here instead!
{
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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