Как вызвать конструктор как функцию?

#c #constructor #call

#c #конструктор #вызов

Вопрос:

Я пытаюсь создать временный объект C для того же самого быстрого вызова в конструкторе и ничего больше.

По какой-то причине это не работает

Вот код:

 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 amp;s: l)
        v->action(amp;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: %sn", s->c_str());
    }
};

//-------------------------------------------------------------------------
int main(int argc)
{
    string_vec_t r;
    r.push_back("1");
    my_visit_items(amp;r /*, 0 */);

    return -1;
}
  

Если у меня есть ctor, принимающий дополнительный аргумент, то никаких проблем. Но в нынешнем виде это не работает, и я не понимаю причину ошибки:

 1>error C2040: 'r': 'my_visit_items amp;' differs in levels of indirection from 'string_vec_t'
1>error C2530: 'r': references must be initialized
  

Комментарии:

1. Почему бы вам не написать функцию?

2. Вызывая do_this(amp;r); вы передаете string_vec_t* , а не string_vec_tamp;

3. do_this(r); для вызова эталонной версии. Удалите оператор addressof.

4. Прошу прощения, пример неверен. «struct do_this: do_what { public: string_vec_t *r; do_this(string_vec_t *r): r(r) { } переопределение действия виртуальной пустоты() { } }; «

5. @BenS Если это неправильно, пожалуйста, отредактируйте вопрос, а не просто оставьте комментарий. Вам также следует уточнить, что именно вы подразумеваете под «по какой-то причине это не работает».

Ответ №1:

my_visit_items(amp;r /*, 0 */); это объявление my_visit_items ссылки r , точно так же, как my_visit_items amp;r; было бы. Попробуйте вместо этого равномерную инициализацию. Вы также должны стараться избегать передачи указателей на строки и векторы по кругу. Код, который вы показали, прекрасно работал бы без указателей:

 #include <iostream>
#include <vector>
#include <string>

typedef std::vector<std::string> string_vec_t;

//-------------------------------------------------------------------------
struct visit_items {
    virtual void action(const std::stringamp; s) = 0;
    virtual ~visit_items() = default;
};

void items_visitor(visit_itemsamp; v) {
    string_vec_t l = {"1", "2", "3", "4"};
    for(autoamp; s : l) v.action(s);
}

struct my_visit_items : visit_items {
    string_vec_tamp; r;
    my_visit_items(string_vec_tamp; r) :
        visit_items{},
        r(r)
    {
        items_visitor(*this);
    }

    virtual void action(const std::stringamp; 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;
}
  

Комментарии:

1. Спасибо тебе, Тед. В этом и заключалась проблема!

Ответ №2:

Когда вы хотите передать ссылку, вам нужно вызвать do_this(r); С помощью calling do_this(amp;r) , на который вы передаете указатель r .

Далее вы можете вызвать конструктор (теоретически) напрямую с помощью do_this::do_this(r);

Но почему бы не использовать функцию, когда вы хотите иметь функцию? Не каждый компилятор позволяет это без явной настройки некоторых параметров компилятора (например, gcc требует -fpersmissive).
Если причина в том, что вы хотите реализовать свою функцию только один раз, то вызовите функцию из конструктора.
Если вы хотите иметь функцию, которая инкапсулируется в class, не требуя атрибутов класса, вы также можете использовать static функцию-член класса.

Комментарии:

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

Ответ №3:

Не связано с ошибками.

В моем 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;
};