Можно ли перегрузить как оператор () как разыменование, так и оператор = как присваивание в одном классе?

Я работаю над программой, которая имеет сетку указателей на объекты, которые указывают либо на значение Null, либо на производный дочерний элемент. Я хочу иметь возможность устанавливать значения в этой сетке по адресу их производного дочернего элемента, чтобы я мог «разместить» дочернего элемента в сетке и получить доступ к дочернему элементу через его расположение в памяти.

Вот как выглядит интерфейс для сетки.

class Grid{

public:
    virtual int get(g_type) const;

public:

    parent* operator() (int,int);

    Grid() : _amtCol(10),_amtRow(10)
    {construct();}

    ~Grid() {deconstruct();}

private:
    int _amtCol;
    int _amtRow;
    parent* **_grid;

private:
    parent ***meddle(access);
    void meddle(access, parent***);
    virtual void construct();
    virtual void deconstruct();
};

Вот как выглядит перегрузка ().

parent* Grid::operator() (int i,int j){

    if(i < get(r_QTY) && j < get(c_QTY)){

        return this->meddle(key)[i+1][j+1];

    }else{return NULL;}
}

Я хочу иметь возможность называть это в остальной части моей программы как:

Grid b;
Child c;
Child c2;

b(1,1) = &c;
b(1,4) = &c2;

b(1,1)->foo(); //calls the first Childs foo()
b(1,4)->foo(); //calls the second Childs foo()

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

Есть ли способ связать перегрузки или что-то подобное, чтобы это работало?

Я подумал, что, возможно, мне нужно сгладить мои перегрузки в родительских и дочерних классах, но они, похоже, отлично работают.

/////////////////////////////////////////////////////

Кроме того, я реализовал это:

void Grid::operator() (int i,int j,parent &cpy){
    if(i < get(r_QTY) && j < get(c_QTY)){
        this->meddle(key)[i+1][j+1] = &cpy;
    }
}

Это позволяет использовать эту функцию.

Вот моя диссертация! Спасибо!

//////////// Быстрое добавление: так что, возможно, мне не обязательно знать, справедливо ли это с моральной и этической точек зрения. У меня есть способ реализовать работающую функциональность. Думаю, я понимаю, что использование того, что уже существует в библиотеке, должно быть предпочтительнее моих собственных творений, но тот факт, что это выполнимо, например, если вы используете std :: vector, означает, что это возможно. Мне интересно, как это стало возможным и где это существует в синтаксисе языка.


person Burns    schedule 24.11.2017    source источник
comment
Не имеет отношения, но может оказаться полезным узнать, почему вам не следует вызывать virtual функции в конструкторе или деструктор   -  person Tas    schedule 24.11.2017
comment
Кроме того, почему ваш деструктор должен быть виртуальным   -  person PaulMcKenzie    schedule 24.11.2017
comment
Ого, это очень полезная информация. Спасибо.   -  person Burns    schedule 24.11.2017
comment
Также узнайте, что такое трехзвездочный программист.   -  person nwp    schedule 24.11.2017
comment
Я не понимаю, почему вы использовали 3 уровня косвенного обращения (parent ***). В чем причина тройных указателей?   -  person PaulMcKenzie    schedule 24.11.2017
comment
Я использовал его как наложение структуры топографических данных для создания динамически изменяющейся двухмерной сетки. . . . Потому что я молод и новичок в программировании и пока еще не знаком с соглашениями и причинами, по которым встроенные реализации предпочтительнее косвенных.   -  person Burns    schedule 24.11.2017
comment
попробуйте решить это с помощью std::vector<std::vector<std::unique_ptr<BaseType>>>.   -  person NathanOliver    schedule 24.11.2017
comment
полиморфны ли ячейки в сетке?   -  person sp2danny    schedule 24.11.2017
comment
да. Я не уверен, каким образом вы конкретно ссылаетесь, но они есть.   -  person Burns    schedule 24.11.2017


Ответы (1)


Не уверен, в чем именно заключается ваш вопрос, но вы можете сделать что-то вроде:

struct parent
{
    virtual ~parent() = default;
    virtual void foo() = 0;
};

struct Child : parent
{
    Child(int n) : n(n) {}
    void foo() override { std::cout << n << std::endl;}
    int n;
};

class Grid{
public:
    Grid() : col(10), row(10), grid(col * row, nullptr) {}

    parent* operator() (std::size_t x, std::size_t y) const {
        if (col <= x || row <= y) { throw std::runtime_error("Invalid arguments"); }
        return grid[y * col + x];
    }

    parent*& operator() (std::size_t x, std::size_t y) {
        if (col <= x || row <= y) { throw std::runtime_error("Invalid arguments"); }
        return grid[y * col + x];
    }

private:
    int col;
    int row;
    std::vector<parent*> grid;
};

И тогда у вас есть:

Grid b;
Child c(1);
Child c2(2);

b(1,1) = &c;
b(1,4) = &c2;

b(1,1)->foo(); //calls the first Childs foo()
b(1,4)->foo(); //calls the second Childs foo()

Демо

person Jarod42    schedule 24.11.2017