Я пытаюсь создать временный объект С++ для того же быстрого вызова в конструкторе и ничего больше.
Почему-то это не работает
Вот код:
typedef std::vector<std::string> string_vec_t;
//-------------------------------------------------------------------------
struct visit_items
{
virtual void action(std::string *s) = 0;
};
void items_visitor(visit_items *v)
{
string_vec_t l = { "1", "2", "3", "4" };
for (auto &s: l)
v->action(&s);
}
struct my_visit_items: visit_items
{
public:
string_vec_t *r;
my_visit_items(string_vec_t *r /*, int */): r(r)
{
items_visitor(this);
}
virtual void action(std::string *s) override
{
r->push_back(*s);
printf("visited: %s\n", s->c_str());
}
};
//-------------------------------------------------------------------------
int main(int argc)
{
string_vec_t r;
r.push_back("1");
my_visit_items(&r /*, 0 */);
return -1;
}
Если у меня есть ctor дополнительный аргумент, то нет проблем. Но в нынешнем виде это не работает, и я не понимаю ошибки:
1>error C2040: 'r': 'my_visit_items &' differs in levels of indirection from 'string_vec_t'
1>error C2530: 'r': references must be initialized
Звоня do_this(&r);
, вы передаете string_vec_t*
, а не string_vec_t&
do_this(r);
за вызов эталонной версии. Удалить адрес оператора.
Прошу прощения, пример неверный. ``` struct do_this: do_what { public: string_vec_t *r; do_this(string_vec_t *r): r(r) { } virtual void action() override { } }; ```
@BenS Если это неправильно, отредактируйте вопрос, а не просто оставляйте комментарий. Вы также должны уточнить, что именно вы подразумеваете под «по какой-то причине это не работает».
Спасибо @john, я решил проблему. Я чувствую себя плохо из-за того, что не получил правильный код в первый раз, а затем получил отрицательный голос за что-то глупое.
Строка "my_visit_items(&r /*, 0 */);" генерирует «ошибка: конфликтующее объявление ‘my_visit_items& r’». Это не то, что вы хотите сделать, но эту ошибку можно устранить с помощью «my_visit_items mvi(& r);»
Ваше описание «создать временный объект C++ для того же быстрого вызова в конструкторе» и некоторые из ваших вариантов кодирования подсказывают мне, что вас может заинтересовать функтор... но в функторах, с которыми я знаком, ctor и dtor оба ничего не делают (что делает их очень быстрыми), а "operator()" выполняет все действия.
Когда вы хотите передать ссылку, вам нужно вызвать do_this(r);
При вызове do_this(&r)
вы передаете указатель на r
.
Далее вы можете вызвать конструктор (теоретически) напрямую с помощью
do_this::do_this(r);
Но почему бы не использовать функцию, если вы хотите иметь функцию? Не каждый компилятор допускает это без явной установки некоторых параметров компилятора (например, gcc требует -fpersmissive).
Если причина в том, что вы хотите реализовать свою функцию только один раз, то вызовите функцию из конструктора.
Если вы хотите, чтобы функция была инкапсулирована в классе, не требуя атрибутов класса, вы также можете использовать функцию-член класса static
.
Спасибо за ваш ответ, у меня был неправильный фрагмент кода, и я обновил его соответствующим образом. Пожалуйста, удалите свой ответ и мои комментарии, чтобы лучше отразить эту тему.
my_visit_items(&r /*, 0 */);
является объявлением my_visit_items
ссылки r
, как и my_visit_items &r;
. Вместо этого попробуйте универсальную инициализацию. Вы также должны стараться избегать передачи указателей на строки и векторы. Код, который вы показали, будет нормально работать без указателей:
#include <iostream>
#include <vector>
#include <string>
typedef std::vector<std::string> string_vec_t;
//-------------------------------------------------------------------------
struct visit_items {
virtual void action(const std::string& s) = 0;
virtual ~visit_items() = default;
};
void items_visitor(visit_items& v) {
string_vec_t l = {"1", "2", "3", "4"};
for(auto& s : l) v.action(s);
}
struct my_visit_items : visit_items {
string_vec_t& r;
my_visit_items(string_vec_t& r) :
visit_items{},
r(r)
{
items_visitor(*this);
}
virtual void action(const std::string& s) override {
r.push_back(s);
std::cout << "Visited: " << s << "\n";
}
};
//-------------------------------------------------------------------------
int main() {
string_vec_t r;
r.push_back("1");
my_visit_items{r}; // { } instead of ( )
return 1;
}
Спасибо, Тед. Вот в чем проблема!
Не связано с ошибками.
В моем Linux g++-v7:
Если вы включите достаточно флагов компилятора, вы можете обнаружить, что компилятор предупреждает об этой структуре:
struct visit_items
{
virtual void action(std::string *s) = 0;
};
с участием
// warning: ‘struct visit_items’ has virtual functions and
// accessible non-virtual destructor [-Wnon-virtual-dtor]
Примечание. Это предупреждение вызывает 2 другие проблемы (где используется класс).
Все это проясняется, когда вы предоставляете виртуальный dtor по умолчанию
struct visit_items
{
virtual ~visit_items() = default;
virtual void action(std::string *s) = 0;
};
Почему бы вам не написать функцию?