Jump to content

    

Есть ли возможность в наследованном классе изменить содержимое массива родительского класса

18 minutes ago, jcxz said:

Так покажите как? Кроме тех методов что уже предложены. 

#include <iostream>                                                                                                                                                                                                                          
                                                                                                                                                                                                                                             
class Base {                                                                                                                                                                                                                                 
    public:                                                                                                                                                                                                                                  
        Base() {}                                                                                                                                                                                                                            
        ~Base() {}                                                                                                                                                                                                                           
                                                                                                                                                                                                                                             
        void * m_array[13];                                                                                                                                                                                                                  
};                                                                                                                                                                                                                                           
                                                                                                                                                                                                                                             
class Derived : public Base {                                                                                                                                                                                                                
    public:                                                                                                                                                                                                                                  
        Derived() {}
        ~Derived() {}
        /* Just for lulz */
        void ** get_base_array_pointer (void) {
            return Base::m_array;
        }
        void ** get_derived_array_pointer (void) {
            return this->m_array;
        }
};

int main(){
    Derived tst_obj;
    std::cout << "Derived class array pointer address (via access) is:" << std::hex << size_t(tst_obj.m_array) << std::endl;
    std::cout << "Derived class array pointer address (via method) is:" << std::hex << size_t(tst_obj.get_base_array_pointer()) << std::endl;
    std::cout << "Base    class array pointer address (via method) is:" << std::hex << size_t(tst_obj.get_derived_array_pointer()) << std::endl;

    Base * p = &tst_obj;

    p->m_array[12] = NULL;
    std::cout << "element is is:" << std::hex << size_t(tst_obj.m_array[12]) << std::endl;

    tst_obj.m_array[12] = (void*)42;
    std::cout << "element is is:" << std::hex << size_t(p->m_array[12]) << std::endl;
}

Результат:
 

$ g++ tst.cpp                                                                                                                                                                                                                                                                                                                                                                            $ ./a.out                                                                                                                                                                                                
Derived class array pointer address (via access) is:7ffef69e5680                                                                                                                                                                             
Derived class array pointer address (via method) is:7ffef69e5680                                                                                                                                                                             
Base    class array pointer address (via method) is:7ffef69e5680                                                                                                                                                                             
element is is:0                                                                                                                                                                                                                              
element is is:2a

Вызов приложения после компиляции пропал. Его съел элемент форума Code.

Edited by one_eight_seven

Share this post


Link to post
Share on other sites
1 hour ago, jcxz said:

А в дочерних классах объявляйте указатель на этот массив.

Но как в дочерхних классах его заполнить? В базовом классе не соберётся метод OpenAllDrivers, т.к. размер массива неизвестен.

48 minutes ago, Forger said:

Простой односвязный список.

Т.е. примерно я думал в правильном направлении. Значит ничего такого из нового стандарта нельзя использовать(( Ну тогда шаблончики вступают в работу)

24 minutes ago, one_eight_seven said:

Его нельзя перегружать. Перегружаются методы.

Нет, давайте об очевидных вещам не будем говорить. Это всё понятно. Я же привёл псевдокод, о чём честно и сообщил в стартовом сообщении. Пусть это будет не массив, а некий std::tuple, или ещё что-то, мне всё равно. Мне нужно, чтобы выполнялись три требования, которые я тоже перечислил в стартовом сообщении.

20 minutes ago, Forger said:

После этого можно смело переходить на старый добрый C 

Угу, а мы от этого уходим.

9 minutes ago, one_eight_seven said:

void * m_array[13];

А почему 13? А если я захочу 24 драйвера туда занести? Или 1? В первом случае будет недабор памяти, а во втором - перебор) Я ищу что-то такое, что легко масштабируется, не привязано к конкретному типу данных (это не проблема, просто упомянул), и кушает памяти ровно столько, сколько нужно. Пока да, односвязный списко лидирует. Он конечно содержит небольшой оверхэд из-за указателей, но по-другому и не сделаешь.

Share this post


Link to post
Share on other sites

А какой смысл в этих?:

10 минут назад, one_eight_seven сказал:

        void ** get_base_array_pointer (void) {
            return Base::m_array;
        }
        void ** get_derived_array_pointer (void) {
            return this->m_array;
        }

Через указатель на базовый тип с потомками работать невозможно. И зачем тогда вообще нужны эти get_base_array_pointer и get_derived_array_pointer???  :wacko2:

И это ещё кроме того, что оба они будут возвращать одно и то же значение: указатель на Base::m_array. И зачем это???

Share this post


Link to post
Share on other sites
3 minutes ago, jcxz said:

Через указатель на базовый тип с потомками работать невозможно.

В коде же работает.

Quote

И зачем тогда вообще нужны эти get_base_array_pointer и get_derived_array_pointer???  :wacko2:

Написано же just for lulz. для тех, кто не понимает, что массив, объявленный в базовом классе  - это тот же массив, что и в наследующем.

Quote

И это ещё кроме того, что оба они будут возвращать одно и то же значение: указатель на Base::m_array.

Собственно, это и демонстрируется.

Если хочется другого и без "не надо говорить очевидные вещи", так прекращайте говорить на омском языке, и излагайте мысли на русском.

Топикстартеру:
Если размер массива заранее неизвестен, то в базовом классе можно объявить два виртуальных (можно и чистых виртуальных) метода - взятия массива и его размера. И эти методы переопределить в наследующих классах (их можно сделать хоть публичными, хоть защищёнными, хоть приватными). А сам массив объявлять и определять в дочерних. Или с VMT тоже не хочется связываться?
Edited by one_eight_seven

Share this post


Link to post
Share on other sites
3 минуты назад, haker_fox сказал:

Но как в дочерхних классах его заполнить? В базовом классе не соберётся метод OpenAllDrivers, т.к. размер массива неизвестен.

Кого заполнить? Массив или указатели на него?

Если первое - он у вас будет static в каждом дочернем - свой. Инициализируется отдельно в .cpp-файле как все static-данные.

Указатель на массив - инициализируется в конструкторе дочернего класса.

Share this post


Link to post
Share on other sites
2 minutes ago, haker_fox said:

Угу, а мы от этого уходим.

Оно и видно :)

 

Share this post


Link to post
Share on other sites
1 минуту назад, one_eight_seven сказал:

В коде же работает.

У Вас там нет замены родительского массива на дочерние. Т.е. - того что нужно ТС. А тот код что Вы привели - бессмысленный.

1 минуту назад, one_eight_seven сказал:

Написано же just for lulz. для тех, кто не понимает, что массив, объявленный в базовом классе  - это тот же массив, что и в наследующем.

ТСу было нужно другое. Ему нужен был свой экземпляр массива в каждом дочернем классе. Т.е. - собственно перегрузка массивов. Как для функций.

3 минуты назад, one_eight_seven сказал:

Если хочется другого и без "не надо говорить очевидные вещи", так прекращайте говорить на омском языке, и излагайте мысли на русском.

Вам бы я порекомендовал читать исходный вопрос. Прежде чем отвечать.

Share this post


Link to post
Share on other sites
1 minute ago, Forger said:

Оно и видно :)

Простите?)

1 minute ago, jcxz said:

Ему нужен был свой экземпляр массива в каждом дочернем классе.

Не совсем. Нужна подмена. Т.е. массив должен быть один в итоге.

4 minutes ago, jcxz said:

Если первое - он у вас будет static в каждом дочернем - свой.

А как же с ним будут работать функции базового класса? Которые в дочерних классах не перегружены.

Share this post


Link to post
Share on other sites
2 minutes ago, jcxz said:

Вам бы я порекомендовал читать исходный вопрос. Прежде чем отвечать.

Прочитал. Массив родительского класса изменяется в дочернем. Размер определён и соберётся во время компиляции. Если в конструктор добавить инициализацию полей - тоже будет сделано компилятором. Никакого динамического создания. Всё по ТЗ.

13 minutes ago, haker_fox said:

А почему 13? А если я захочу 24 драйвера туда занести? Или 1? В первом случае будет недабор памяти, а во втором - перебор) Я ищу что-то такое, что легко масштабируется, не привязано к конкретному типу данных (это не проблема, просто упомянул), и кушает памяти ровно столько, сколько нужно. Пока да, односвязный списко лидирует. Он конечно содержит небольшой оверхэд из-за указателей, но по-другому и не сделаешь.

Показать по-другому?
 

Quote

В базовом классе не соберётся метод OpenAllDrivers

Его нет в базовом. Он у вас появляется в дочернем.

Share this post


Link to post
Share on other sites
8 minutes ago, haker_fox said:

Простите?)

Речь про код в первом посте на этой странице. Возвращать указатель на внутренние данные класса и наличие двойного указателя в плюсах - это вообще тотальный уход в С.

К чему тут С++ и уж тем более С++17 - вообще загадка.

 

Share this post


Link to post
Share on other sites
6 minutes ago, one_eight_seven said:

Размер определён и соберётся во время компиляции.

Как же он определён?

6 minutes ago, one_eight_seven said:

Показать по-другому?

Да.

 

7 minutes ago, one_eight_seven said:

Размер определён и соберётся во время компиляции.

Вы его задаёте "в лоб", указывая размер. А мне нужно, чтобы размер был рассчитан самим компилятором на этапе сборки. Я думал, это следует из комментария к массиву для базового класса и псевдокода дочернего класса.

 

4 minutes ago, Forger said:

Речь про код в первом посте на этой странице.

В первом посте мой код. Там нет никаких двойных указателей. И они тем более не возвращаются. Вы наверно о коде @one_eight_seven говорите...

12 minutes ago, one_eight_seven said:

Его нет в базовом. Он у вас появляется в дочернем.

Сейчас возможности проверить нет. Но что-то тут не так.

Share this post


Link to post
Share on other sites
5 minutes ago, haker_fox said:

. Вы наверно о коде @one_eight_seven говорите...

Ну да: ))

6 minutes ago, Forger said:

Речь про код в первом посте на этой странице.

 

Share this post


Link to post
Share on other sites
10 minutes ago, haker_fox said:

Да.

#include <iostream>

using namespace std;

class Base {
    public:
        Base() {}
        ~Base() {}

        void open_all_drivers() {
            size_t size = get_size();
            int * p = get_array();
            for (size_t i = 0; i<size; ++i){
                cout << dec << i << "'th element is: " << hex << p[i] << endl;
            }
        }
    private:
        virtual int * get_array() = 0;
        virtual int get_size() = 0;
};

class Derived : public Base {
    public:
        Derived() {
            size_t size = get_size();
            int * p = get_array();
            for (size_t i = 0; i<size; ++i){
                p[i] = 0x100 + i;
            }
        }
        ~Derived() {}
    private:
        int m_array[12];
        virtual int * get_array() final {
            return m_array;
        }
        virtual int get_size() final {
            return sizeof(m_array)/sizeof(int);
        }
};

static Derived tst;

int main(){
    Base * p = &tst;
    p->open_all_drivers();
    return 0;
}

 

Share this post


Link to post
Share on other sites

@one_eight_seven, уже понятнее. Но! Задача решена хоть и через классы, но по-сути используя сишные указатели...((( Мне нужно было красивое решение. Согласен, термин нетехническй. Но я привёл ссылку на хабру, где коллега с нашего сайта использовал tuple. Получилось очень красиво... Я имел в виду что-то подобное из нового стандарта. И это я написал явно... Все эти тасования указателей - действительно возврат к Си, хоть и спрятанный за классами. Простите, что резковато. Но вы не совсем уловили то, что мне нужно.

Share this post


Link to post
Share on other sites
11 minutes ago, haker_fox said:

Вы его задаёте "в лоб", указывая размер. А мне нужно, чтобы размер был рассчитан самим компилятором на этапе сборки. Я думал, это следует из комментария к массиву для базового класса и псевдокода дочернего класса.

Компилятор не будет рассчитывать, более того, код типа:
type * m_array[] -- это, на самом деле type* m_array[0];

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now