В конструкторе кандидат ожидает 1 аргумент, 0 при условии [дубликат]

этот вопрос уже есть ответ здесь:

этот код:

class cat
{
    private:
        int height;
    public:
        cat (int inputHeight);
};

cat::cat (int inputHeight)
{
    height = inputHeight;
}

class twoCats
{
    private:
        cat firstCat;
        cat secondCat;
    public:
        twoCats (cat theFirstCat);
        void addSecondCat (cat theSecondCat);
};

twoCats::twoCats (cat theFirstCat)
{
    firstCat = theFirstCat;
}

void twoCats::addSecondCat (cat theSecondCat)
{
    secondCat = theSecondCat;
}

int main() {return 0;}

и это ошибки:

main.cpp: In constructor ‘twoCats::twoCats(cat)’:
main.cpp:24:34: error: no matching function for call to ‘cat::cat()’
main.cpp:24:34: note: candidates are:
main.cpp:9:1: note: cat::cat(int)
main.cpp:9:1: note:   candidate expects 1 argument, 0 provided
main.cpp:1:7: note: cat::cat(const cat&)
main.cpp:1:7: note:   candidate expects 1 argument, 0 provided
main.cpp:24:34: error: no matching function for call to ‘cat::cat()’
main.cpp:24:34: note: candidates are:
main.cpp:9:1: note: cat::cat(int)
main.cpp:9:1: note:   candidate expects 1 argument, 0 provided
main.cpp:1:7: note: cat::cat(const cat&)
main.cpp:1:7: note:   candidate expects 1 argument, 0 provided

Я не понимаю следующее:

  1. почему конструктор для twoCats пытаться вызвать конструктор по умолчанию для cat? Конечно, ему не нужно создавать экземпляр cat а когда twoCats инициализируется, ему будет передан уже инициализированный экземпляр cat который будет передан ?
  2. почему один и тот же блок сообщений об ошибках отображается дважды? Я позвал!--8--> на Ubuntu 12.04.

4 ответов


вам нужен конструктор по умолчанию или инициализировать объекты cat в twoCats список инициализации конструктора явно, чтобы избежать построения по умолчанию.

почему конструктор для twoCats пытается вызвать значение по умолчанию конструктор для кошки? Конечно, ему не нужно создавать экземпляр cat, поскольку при инициализации twoCats он будет передан уже инициализированный экземпляр cat, которому будет передана высота int спор?

это необходимо построить значения по умолчанию для cat объекты

private:
    cat firstCat;
    cat secondCat;

в классе twoCats потому что вы не инициализировать их. В вашем конструкторе

cat::cat (int inputHeight)
{
    height = inputHeight;
    ^^^^^^^^^^^^^^^^^^^^
}   // this is assignment

это назначение уже созданным объектам.

правило выглядит следующим образом: если вы не инициализируете экземпляры явно в ctor список инициализации после

  1. по умолчанию ctor называется
  2. вы в конечном итоге назначаете уже построенным по умолчанию объектам в ctor тело.

таким образом, вам грозит штраф за дополнительные вызовы, если вы не инициализируете в списке инициализации.

стандарт C++ n3337 § 12.6.2 / 10 инициализация баз и членов

в конструкторе без делегирования инициализация продолжается в следующий порядок:

- во-первых, и только для конструктор наиболее производного класса (1.8), виртуальные базовые классы инициализируются в порядке их появляются на глубина-первый слева направо обход направленного ациклического графа базовые классы, где "слева направо" - порядок появления базовые классы в производном классе base-specifier-list.

- тогда, прямые базовые классы инициализируются в порядке объявления, а они отображаются в списке base-specifier-list (независимо от порядка mem-инициализаторы).

- затем инициализируются нестатические члены данных в порядке они были объявлены в определении класса (опять же независимо от порядка mem-инициализаторы).

- наконец, выполняется составная инструкция тела конструктора.

[ Примечание: порядок объявления уполномочен обеспечить, чтобы база и элементы subobjects уничтожаются в обратном порядке инициализация. - конец Примечания ]

вот демо-код.


Я бы инициализировал класс twoCats такой:

class twoCats
{
private:
    cat firstCat;
    cat secondCat;
public:
    twoCats (const cat& theFirstCat, const cat& theSecondCat)
        : firstCat (theFirstCat), secondCat (theSecondCat)
    {
    }

};

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

инициализация членов данных является довольно сложной проблемой в C++, я предлагаю Вам google.

в частности, поскольку у вас есть два члена типа класса, компилятор, несмотря ни на что, пытается инициализировать их в конструкторе. Он делает это для каждого кота, что, вероятно, является причиной того, что вы получаете блок сообщения об ошибке дважды. По умолчанию компилятор пытается инициализировать элементы данных cat с помощью конструктора по умолчанию, т. е. без аргументов. К сожалению, cat не имеет конструктора по умолчанию, так как вы объявили его с одним аргументом. Другими словами, каждая кошка должна быть инициализирована одним аргументом (или скопирована, или перемещена C++11).

Я не рекомендую объявлять дополнительный конструктор в cat без аргументов: кажется, что нет" высоты по умолчанию " кошки, а -1 предложенный другим ответом очень странный: он, похоже, не создает допустимый объект, и вам нужно будет проверить это значение по умолчанию, прежде чем использовать любой из 'ы.

EDIT:это с точки зрения формата. Что касается семантики вашей программы, может быть неправильно копировать кошки. Возможно, вам нужна ссылка (или указатель) на объекты, с которыми вы инициализировали свои twoCats, возможно, нет.


оба экземпляра cat должны быть инициализированы в момент, когда они начинают существовать.

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

простой и безопасный способ сделать это, чтобы использовать std::vector для хранения экземпляров.

class cat
{
    private:
        int height;
    public:
        cat (int inputHeight);
};

cat::cat (int inputHeight)
{
    height = inputHeight;
}

#include <vector>
#include <utility>

class twoCats
{
    private:
        std::vector<cat> cats_;

    public:
        twoCats (cat theFirstCat)
        { cats_.push_back( std::move( theFirstCat ) ); }

        void addSecondCat (cat theSecondCat)
        { cats_.push_back( std::move( theSecondCat ) ); }
};

int main() {return 0;}

кроме того, вы можете использовать boost::optional.

или динамически выделять экземпляры (используйте интеллектуальный указатель, например unique_ptr для управления временем жизни).

или давайте кошки по умолчанию конструктивны.


как отмечено "thang" в комментарий, оригинальный дизайн не гарантирует, что twoCats две кошки. У него может быть только одна кошка, или три, или больше. Так что было бы неплохо изменить конструкцию.

например, есть конструктор, который принимает два аргумента cat или высоты cat.

или для другого примера, изменение имени twoCats.


как имя вашего класса (twoCats) заявляет, что он представляет двух кошек всегда. Эти котята могут быть живыми, мертвыми или даже еще не родился. Но их будет двое.

ваш дизайн неправильный в том смысле, что либо:

  • cat должен иметь возможность представлять нерожденную кошку (поэтому она должна иметь открытый конструктор по умолчанию, устанавливающий объект в нерожденное состояние изначально) или
  • ваш конструктор twoCats должен принимать ровно двух кошек на самого начала.