Как вызвать конструктор как функцию? - PullRequest
0 голосов
/ 08 апреля 2019

Я пытаюсь создать временный объект 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 &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

Ответы [ 3 ]

2 голосов
/ 08 апреля 2019

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;
}
1 голос
/ 08 апреля 2019

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

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

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

0 голосов
/ 09 апреля 2019

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

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