Компилятор считает, что я передаю std :: ofstream * &, передавая std :: ofstream *

0

Недавно я написал класс журнала. При компиляции этого кода:

std::ofstream *stream = new std::ofstream;
stream->open( log_file_name.c_str() );

assert( stream->is_open() );

logger( stream, std::string("blurp") );

Я получаю сообщение об ошибке:

no match for call to '(name::space::logger)( std::ofstream*&, std::string )'

в отношении последней строки кода.

Файл заголовка, определяющий регистратор:

namespace name {
    namespace space {
        class logger {
private:                
            std::ofstream *stream;
            std::string name;
public:                
            void log( std::string, std::string );
            logger( std::ofstream *, std::string );
            logger();
        };
    }
}

И я реализовал все функции/конструкторы, прототипированные там без ошибок.

Что может быть причиной этого? Спасибо за ваше время, Эрлинг.

  • 2
    Я скомпилировал ваш код, и он работал. Кстати, не используйте указатель на ofstream, плохой стиль кодирования.
  • 0
    Опубликовать тест-кейс. Это может быть так просто, как не включать необходимые заголовочные файлы.
Показать ещё 4 комментария
Теги:
pointers

3 ответа

1
Лучший ответ

Компилятор считает, что вы вызываете operator() на объект, называемый logger. Кажется, что вы хотите сделать, это создать экземпляр logger:

logger log(stream, std::string("blurp") );

Здесь log - это экземпляр класса name::space::logger.

  • 0
    Насколько я вижу, нет объекта с именем logger. logger(stream, string("blurp")); вызовет конструктор, создав безымянный временный. Если только я не вижу некой «самой неприятной проблемы».
  • 0
    Это была моя проблема. Код был в конструкторе для другого класса, и регистратор был членом класса. Я ошибочно думал, что синтаксис применяется к объекту default-constructor. logger = name :: space :: logger (stream, std :: string ("blurp")); починил это.
1

GCC имеет этот странный способ сообщения типов аргументов функции.

Когда вы это сделаете:

logger( stream, std::string("blurp") );

компилятор видит вызов конструктора logger (name::space::logger), первый аргумент которого является значением lvalue (в данном случае простой переменной) типа std::ostream*, а второй является rvalue (временным построенный на месте) типа std::string. Он сообщает об этом в качестве сигнатуры вызова (name::space::logger)(std::ostream*&, std::string) - ссылка & (значение lvalue) здесь просто указывает, что аргумент является lvalue. Это не влияет на возможность сопоставить его с типом параметра std::ostream*.

  • 0
    Хотя это действительно хорошее и точное объяснение того, почему компилятор ищет и сообщает об этой точной сигнатуре, это не объяснение, почему он может не найти функцию.
  • 0
    Правда, я только ответил на заголовок вопроса.
1

Прежде всего, нет необходимости использовать указатель для ostream. Поскольку это не Java, вы можете создавать объекты в стеке и без new.

Тогда похоже, что ваш компилятор не видел, что у logger есть конструктор с указателем потока и строкой. Из вызываемого вами вызова предполагается, что подпись должна быть чем-то вроде std::ofstream*&, std::string, но предоставленный вами конструктор идеально соответствует этому предположению (см. Ответ Sebastian Redl для деталей).

Итак, что здесь может быть не так?

  1. Компилятор вообще не видит заголовок. Это было бы потому, что вы не включили его. Я не думаю, что это вероятно, потому что сообщение об ошибке должно быть другим (говорить что-то о logger классов не было определено)
  2. Компилятор видит другую версию заголовка, которая не содержит конструктор, который вы хотите вызвать здесь. Это может быть связано с тем, что вы не сохранили заголовок после редактирования в конструкторе, или, может быть, вы скопировали его в другое место, а директива #include найдет более старую версию, а не ту, в которую вы ввели конструктор. Лучшая возможность найти это введя некоторую явную ошибку в заголовке и снова скомпилируем. Если компилятор не жалуется на ошибку, он явно не включает заголовок, который вы редактируете.
  • 0
    Я использовал указатель не потому, что я эмулирую Java (у меня вообще нет никакого опыта в этом), а потому, что я хочу, чтобы несколько классов логгера записывали в один и тот же файл. Я не был уверен в нескольких потоках для одного файла, и, поскольку моя программа однопоточная, я не думал, что использование одного потока вызовет скачки данных.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню