【问题标题】:"Default constructor cannot be referenced" errormessage - is using a default constructor mandatory in my case? (Learning OOP)“无法引用默认构造函数”错误消息 - 在我的情况下是否必须使用默认构造函数? (学习面向对象)
【发布时间】:2020-05-02 18:43:44
【问题描述】:
#include <iostream>
#include <array>
#include <algorithm>
#include <cstdlib>
#include <ctime>
#include <random>
#include <iterator>
#include <string>

class Deck;

class Card
{
public:
    enum cRanks
    {
        RANK_2,
        RANK_3,
        RANK_4,
        RANK_5,
        RANK_6,
        RANK_7,
        RANK_8,
        RANK_9,
        RANK_10,
        RANK_J,
        RANK_Q,
        RANK_K,
        RANK_A,

        MAX_RANKS,
        RANK_AIR
    };

    enum cSuits
    {
        SUIT_CLUBS,
        SUIT_DIAMONDS,
        SUIT_HEARTS,
        SUIT_SPADES,

        MAX_SUITS,
        SUIT_AIR
    };

private:
    cRanks m_rank{RANK_A};
    cSuits m_suit{SUIT_SPADES};

public:
    //Card() = default;

    Card(cRanks r, cSuits s)
        :m_rank{ r }, m_suit{ s }
    {
    }

    void print() const
    {
        char rank{};
        char suit{};
        switch (m_rank)
        {
            case(RANK_2): rank = '2'; break;
            case(RANK_3): rank = '3'; break;
            case(RANK_4): rank = '4'; break;
            case(RANK_5): rank = '5'; break;
            case(RANK_6): rank = '6'; break;
            case(RANK_7): rank = '7'; break;
            case(RANK_8): rank = '8'; break;
            case(RANK_9): rank = '9'; break;
            case(RANK_10): rank = 't'; break;
            case(RANK_J): rank = 'J'; break;
            case(RANK_Q): rank = 'Q'; break;
            case(RANK_K): rank = 'K'; break;
            case(RANK_A): rank = 'A'; break;
            case(RANK_AIR): rank = '_'; break;
            default: rank = '?';
        }
        switch (m_suit)
        {
            case(SUIT_CLUBS): suit = 'C'; break;
            case(SUIT_DIAMONDS): suit = 'D'; break;
            case(SUIT_HEARTS): suit = 'H'; break;
            case(SUIT_SPADES): suit = 'S'; break;
            case(SUIT_AIR): suit = '_'; break;
            default: suit = '?';
        }
        std::cout << rank << suit << ' ';
    }

    friend Deck; 
};

class Deck
{
public:
    using array_type = std::array<Card, 52>;
    using index_type = int;
private:
    array_type m_deck;
    index_type m_index{ 0 };

public:
    Deck()
    {
        m_index = 0;
        int index{0};
        for (int s{ 0 }; s < Card::MAX_SUITS; ++s)
        {
            for (int r{ 0 }; r < Card::MAX_RANKS; ++r)
            {
                m_deck[index].m_rank = static_cast<Card::cRanks>(r);
                m_deck[index].m_suit = static_cast<Card::cSuits>(s);
                index++;
            }
        }
    }

    void print()
    {
        if (m_index > static_cast<int>(m_deck.size()) - 1)
        {
            std::cout << "\nDeck out of cards!";
            return;
        }
        std::cout << '\n';
        for (int i{ m_index }; i < m_deck.size(); ++i)
            m_deck[i].print();
    }

    void shuffle(unsigned int seed = 777)
    {
        std::mt19937 g{ seed };
        std::shuffle(m_deck.begin(), m_deck.end(), g);
    }

    const Card& draw()
    {
        if (m_index > static_cast<int>(m_deck.size()) - 1)
        {
            std::cout << "\nDeck out of cards!";
            return Card(Card::RANK_AIR, Card::SUIT_AIR);
        }
        return m_deck[m_index++];
    }
};

int main()
{
    Deck deck{};
    deck.print();
    deck.shuffle();
    deck.print();



    return 0;
}

简单的二十一点游戏练习来学习 OOP。在上面的代码中,我在 Deck 构造函数上收到错误消息“无法引用的默认构造函数——它是一个已删除的函数”。假设我的 m_deck 数组无法实例化,以便 Deck 的构造函数可以为其赋值,因为 Card 类没有默认构造函数,是否明智?如果我希望我的默认 Card 构造函数有参数怎么办?我可以避免使用“Cards() = default;”吗?在我的卡片课上?我在想只有在你定义了它的性质(等级和花色)的情况下实例化一个 Card 对象才是明智的。

【问题讨论】:

  • This question 可能会给你一个答案,但我不确定它是否能像我想要的那样清楚地回答你的具体情况。如果您在阅读后有任何疑问,可以编辑您的问题。
  • 您需要默认构造函数来初始化数组的元素,或者您必须使用list initialization 提供必要的参数(这取代了对嵌套for 循环的需要)。还有其他选择,但they get weird.

标签: c++ oop constructor


【解决方案1】:
  1. 在没有复制构造函数的情况下,没有从返回类型 const Card& 构造 Card() 对象的方法; constexpr Card::Card(const Card&)
  2. 编译器想使用你提供的默认构造函数 或由它生成以匹配 std::array 中的返回类型 Card。因此, /usr/include/c++/7/array:94:12: error: no matching function for call to ‘Card::Card()
  3. 我试图用最少的东西复制您的代码 外加的 Card() = default; Card(const Card&amp; other) = default; 它似乎至少正在编译。我无法检查功能方面 你。
#include <iostream>
#include <array>

class Deck;

class Card
{
public:
    enum cRanks
    {
        RANK_A,
        MAX_RANKS,
        RANK_AIR
    };

    enum cSuits
    {
        SUIT_SPADES,
        MAX_SUITS,
        SUIT_AIR
    };
private:
    cRanks m_rank{RANK_A};
    cSuits m_suit{SUIT_SPADES};

public:
    Card() = default;

    Card(const Card& other) = default;

    Card(cRanks r, cSuits s)
        :m_rank{ r }, m_suit{ s }
    {
    }

    void print() const
    {
        char rank{};
        char suit{};
        switch (m_rank)
        {
            case(RANK_A): rank = '_'; break;
            default: rank = '?';
        }
        switch (m_suit)
        {
            case(SUIT_SPADES): suit = 'C'; break;
            default: suit = '?';
        }
        std::cout << rank << suit << ' ';
    }

    friend Deck; 
};

class Deck
{
public:
    using array_type = std::array<Card, 52>;
    using index_type = int;
private:
    array_type m_deck;
    index_type m_index{ 0 };

public:
    Deck()
    {
    }

    void print()
    {
    }

    void shuffle(unsigned int seed = 777)
    {
    }

    const Card& draw()
    {
    }
};

int main()
{
    Deck deck{};
    deck.print();
    deck.shuffle();
    deck.print();



    return 0;
}

【讨论】:

  • 第一点不正确。虽然我通常推荐Card(const Card&amp; other) = default;,就像您在代码示例中所做的那样非常明确,但请注意这里是防止编译器在没有提示的情况下自动生成默认的复制构造函数。 constexpr 添加到操作中的内容尚不清楚。你应该多解释一下。
  • 第二点,措辞令人困惑。 Card 不是返回类型,这使得对错误原因的解释难以理解。
  • 第三点偏题了。提问者想知道除了Card() = default; 之外是否还有其他方法可以使他们的代码正常工作。你没有解决这个问题。
  • 您在回答中建议,此代码的用户要么需要默认构造函数来初始化数组的元素,要么需要其他方式来解决。我认为这个类的用户必须在你的答案和他们选择不提供默认构造函数之间做出决定,即使我想要它背后的基本原理。
猜你喜欢
  • 2013-09-09
  • 2021-04-02
  • 2012-11-26
  • 2011-11-03
  • 2023-03-20
  • 1970-01-01
  • 2020-11-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多