LINUX.ORG.RU

Сломал мозг

 


0

4

Возвращаясь к предыдущей теме: http://www.linux.org.ru/forum/development/9153691

Этот подход получился неудачным.
Поэтому попробую заново сформулировать вопрос по-другому.

Есть 10-20 материалов, у которых есть свойства p1, p2, ...
(в зависимости от материала набор этих свойств может отличаться).
Это можно задать через struct mat{...}. Также у каждого материала есть вычисляемые функции, т.е. методы (у каждого они разные).
Можно все это обернуть в class на основе виртуального класса.

Все эти материалы нужно будет передавать в процедуру.
Т.к. количество материалов может быть разной,
то необходимо их передавать либо в виде списков, массивов или еще как-то.

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

Каким методом все это реализовать, чтобы получался код наглядным и простым?
С помощью каких элементов с++ это лучше всего будет сделать. В основном интересует сам подход.

З.ы. Если это возможно, то в рамках стандартного с++98.

★★★★★

Ответ на: комментарий от Zodd

Тут всё чётко и лаконичто, что тебе не понятно?

Можно сделать в С++ стайле и запилить массив на обработчик в структурку - будет красивее, но будет оверхед.

Для каждого твоего материала ты создаёшь функцию обработчик и структуру для хранения. Первым елементом в любой структуре - это её номер.

Потом ты записываешь их последовательно друг за другом в кучу, а потом обходишь - каждая функция обработчик увеличивает твой указатель на длинну её структуры.

Такое на С++ шаблонах ты даже не распарсишь, поэтому это намного красивее С++ кода.

superhackkiller1997
()
Ответ на: комментарий от superhackkiller1997

Можно сделать в С++ стайле и запилить массив на обработчик в структурку - будет красивее, но будет оверхед.

Запилить указатель на обработчик в структуру - тут обишка.

superhackkiller1997
()
Ответ на: комментарий от superhackkiller1997

Зачем делать ООП-ными методами на Си, если на нем нет прямой поддержки ООП?

...будет оверхед.

Нашел где искать оверхед)

Потом ты записываешь их последовательно друг за другом в кучу, а потом обходишь - каждая функция обработчик увеличивает твой указатель на длинну её структуры.

Чем это лучше итераторов?

Вот чем твой код лучше этого?

Zodd ★★★★★
() автор топика
Последнее исправление: Zodd (всего исправлений: 1)
Ответ на: комментарий от Zodd

Зачем делать ООП-ными методами на Си, если на нем нет прямой поддержки ООП?

Это не ООП-стиль, этот стиль был тогда, когда и твой С++ и ООП под стол ходили.

Норм пацаны так и пишут на сишки, а тот сишка-код, который ты видел - писали пацаны уровня 2-го курса недовуза.

Нашел где искать оверхед)

Ну про это ты мне можешь не рассказывать.

Чем это лучше итераторов?

Итераторы исть подобие указателей - твой вопрос не корректен, а првильно он звучит так: Чем подобие лучше указателей?

А потом, это лучше тем, что оно может ободить что угодно - для этого не надо писать новые классы, методы, хренотоды и прочую байду.

Вот чем твой код лучше этого?

Ну во первых - он меньше, лучше, проще. А во вторых - твой код так не может, я не зря там в одной написал a, b, а в другой a, b, с.

Да я и не говорил, что он лучше - тут пациенты писали, что сишка не может, а она может и получше, чем плюсы.

Если юзать глобальные переменные( статик, если у тебя угодно), то это будет ровно в 2раза меньше строк, чем в плюсах.

И это не считая тех строк, что находятся в кишках стл.

Плюс - я могу дампить это просто write()'ом, я могу это спокойно передать куда-то через сокеты, а потом 2-мя строчками там вызывать. У этого подхода столько плюсов в долгострочной перспективе, что твоё обощённое С++ ООП просто детсад по сравнинию с этим.

superhackkiller1997
()
Ответ на: комментарий от superhackkiller1997

А во вторых - твой код так не может, я не зря там в одной написал a, b, а в другой a, b, с.

почему?

anonymous
()
Ответ на: комментарий от superhackkiller1997

Ну во первых - он меньше, лучше, проще.

  return ++ptr;

неконтролируемый выход за границы выделенной памяти

anonymous
()
Ответ на: комментарий от superhackkiller1997

А потом, это лучше тем, что оно может ободить что угодно - для этого не надо писать новые классы, методы, хренотоды и прочую байду.

Ага и утечки тоже умеет.

Ну во первых - он меньше, лучше, проще. А во вторых - твой код так не может, я не зря там в одной написал a, b, а в другой a, b, с.

Могет.

Если юзать глобальные переменные( статик, если у тебя угодно), то это будет ровно в 2раза меньше строк, чем в плюсах.

Глобальные переменные это не есть гут.

Zodd ★★★★★
() автор топика
Ответ на: комментарий от Stil

В структуре члены по-умолчанию открыты, в классе - закрыты.

struct Foo
{
    Foo() {}
};

class Bar
{
public: // разница
    Bar() {}
};
numas13
()
Ответ на: комментарий от Zodd

Ага и утечки тоже умеет.

Какие утечки? Утечки - это проблемы уровня детсада и твоего детсадоского понимания и плюсов. Тут никаких утечек неможет быть по определению.

Могет.

Нет. Твой так не может. Царь сказал - либо подумай чем они отличаются, либо не неси фигню.

Глобальные переменные это не есть гут.

Реально? Ты мне будешь рассказывать то, что ты услышал от соседей по парте? Чем не гуд, нука давай, удиви меня.

superhackkiller1997
()
Ответ на: комментарий от anonymous

Царь сказал нужно - значит нужно. Это ему даёт возможность выпилить его детсадовский текстовый парсер и парсить файлы за сискол и так же дампить.

superhackkiller1997
()
Ответ на: комментарий от superhackkiller1997
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;
 
struct A {
    virtual void fun() = 0;
    virtual ~A() {}
};
 
#define p(a) ", " #a " = " << a
struct B: A {
    int a,b,c;
    void fun() {cout << "id = 0" << p(a) << p(b) << p(c) << endl;}
};
 
struct C: A {
    int a,b;
    void fun() {cout << "id = 1" << p(a) << p(b) << endl;}
};
 
void proc(vector<A*>& a) {
    for_each(a.begin(),a.end(),mem_fun(&A::fun));
}
 
int main() {
    B b;
    C c;
    b.a = 100123; b.b = 100223; b.c = 100323;
    c.a = 200123; c.b = 200223;

    vector<A*> a(2);
    a.at(0) = &b;
    a.at(1) = &c;
 
    proc(a);

    return 0;
}
anonymous
()
Ответ на: комментарий от superhackkiller1997

глобальный массив указателей на функцию и может быть изменен по ходу выполнения программы

anonymous
()
Ответ на: комментарий от superhackkiller1997

Какие утечки? Утечки - это проблемы уровня детсада и твоего детсадоского понимания и плюсов. Тут никаких утечек неможет быть по определению.

уже ответили.

Чем не гуд, нука давай, удиви меня.

Тем, что теряется принцип модульности программ.

Zodd ★★★★★
() автор топика
Ответ на: комментарий от anonymous

вот пример:

./run.sh
---0------------------
#!/bin/bash

echo "---0------------------"
cat run.sh
echo "---1------------------"
cat a.c
echo "---2------------------"
cat b.c
echo "---3------------------"
cat main.c
echo "---4------------------"
gcc a.c b.c main.c
echo "---5------------------"
./a.out
echo "---6------------------"
---1------------------
int counter;
int incCounter_a() { return ++counter; }
---2------------------
int counter;
int incCounter_b() { return ++counter; }
---3------------------
#include <stdio.h>
int incCounter_a();
int incCounter_b();
int main(int argc, char* argv[])
{
  int i;
  for(i=0;i<3;i++)
  {
    printf("counter_a=%i\n", incCounter_a());
    printf("counter_b=%i\n", incCounter_b());
  }
  return 0;
}
---4------------------
---5------------------
counter_a=1
counter_b=2
counter_a=3
counter_b=4
counter_a=5
counter_b=6
---6------------------
планировалось, что incCounter_X добавляет единицу к своему и возвращает полученное число.
static int counter;
решает эту проблему, но делает глобальную переменную видимой только в текущей единице трансляции.

anonymous
()
Ответ на: комментарий от Zodd

уже ответили.

Кто ответил? Детсадовец. Мой тебе совет, пока не подучишь матчасть про всякие там памяти и прочее даже не говори. Когда ты подучишь эту самую матчасть - тогда ты поймёшь, что такое память.

Тем, что теряется принцип модульности программ.

Какой принцип, какой модульности? Осиль статик, осиль ___l и прочее.

superhackkiller1997
()
Ответ на: комментарий от superhackkiller1997

доказывалось утверждение, что его код может выполнять ту же функцию, что и твой код. что не так в доказательстве?

anonymous
()
Ответ на: комментарий от superhackkiller1997

___осиль.

хорошо, вот код, опять не работает почему-то:

./run.sh
---0------------------
#!/bin/bash

echo "---0------------------"
cat run.sh
echo "---1------------------"
cat a.c
echo "---2------------------"
cat b.c
echo "---3------------------"
cat main.c
echo "---4------------------"
gcc a.c b.c main.c
echo "---5------------------"
./a.out
echo "---6------------------"
---1------------------
int ___counter;
int incCounter_a() { return ++___counter; }
---2------------------
int ___counter;
int incCounter_b() { return ++___counter; }
---3------------------
#include <stdio.h>
int incCounter_a();
int incCounter_b();
int main(int argc, char* argv[])
{
  int i;
  for(i=0;i<3;i++)
  {
    printf("counter_a=%i\n", incCounter_a());
    printf("counter_b=%i\n", incCounter_b());
  }
  return 0;
}
---4------------------
---5------------------
counter_a=1
counter_b=2
counter_a=3
counter_b=4
counter_a=5
counter_b=6
---6------------------

anonymous
()
Ответ на: комментарий от anonymous

Мне даже лень читать твоё щитстайл фуфло. Не реботает - твои проблемы, ибо у меня всё работает, а что возникло в твоей анскильной головушке - меня мало волнует.

superhackkiller1997
()
Ответ на: комментарий от superhackkiller1997

Его код и не может

он написал свое сообщение до тебя (Zodd *** (29.05.2013 12:44:58), superhackkiller1997 (29.05.2013 17:49:22)). вполне логично, что его код не работает для задачи, решение которой ты привел спустя 5 часов. но он легко может быть переписан, что и показано.

тут нет наследования

этот код означает наследование:

struct B: A

anonymous
()
Ответ на: комментарий от anonymous

А ну да, и что ты наследуешь? Пустоту? Если бы ты осилил плюсы на уровне чуть выше детсада - ты бы такую фигню не нёс, но тыж мастер фуфланесения.

superhackkiller1997
()
Ответ на: комментарий от superhackkiller1997

А ну да, и что ты наследуешь?

виртуальную функцию, я так полагаю. и в цикле её использую.

anonymous
()
Ответ на: комментарий от superhackkiller1997

это ответ на удивление о названии «пространство имен». стандарт в этом отношении лучший источник, мне так кажется.

anonymous
()
Ответ на: комментарий от anonymous

Я не об названии, а о том, зачем ты его приплёл? Какое оно отношение имеет к твоему балабольству про глобальные переменные и как оно что-то там засаряет?

superhackkiller1997
()
Ответ на: комментарий от superhackkiller1997

описание проблемы, в самом простом случае, приведено в коде. в нем есть две функции в разных файлах, которые используют «свои собственные» глобальные переменные, будучи собранным воедино данный проект перестает работать. причина, по которой код не работает - глобальные переменные и пространство имен.

anonymous
()
Ответ на: Царь в треде. от superhackkiller1997

Не хочу вступать в спор, просто интересует ваше мнение.

numas@gnunix ~ $ g++ -Wall -O2 -std=gnu++0x -o app app.cc
numas@gnunix ~ $ ./app
0x804c008: allocaled 100500 bytes
0x804c008: reserved 16 bytes, currp = 0x804c008
0x804c008: reserved 12 bytes, currp = 0x804c018
0x804c008: reserved 12 bytes, currp = 0x804c024
0x804c008: reserved 16 bytes, currp = 0x804c030
0x804c008: reserved 16 bytes, currp = 0x804c040
0x804c008: reserved 12 bytes, currp = 0x804c050
0 0
0 0
10 0
1 2
3 2
1000 200
~id_0
~id
~id_1
~id
~id_1
~id
~id_0
~id
~id_0
~id
~id_1
~id
0x804c008: pool destroyed
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <algorithm>
using namespace std;

template<class T>
struct pool
{
    static void pool_create(size_t size = 1024 * 1024)
    {
        m_begp = m_curp = m_endp = (char *) malloc(size);
        if(m_begp == NULL) {
            perror("pool::malloc");
            exit(EXIT_FAILURE);
        }
        m_endp += size;
        printf("%p: allocaled %u bytes\n", m_begp, size);
    }

    static void pool_destroy()
    {
        free(m_begp);
        printf("%p: pool destroyed\n", m_begp);
    }

    void * operator new(size_t size)
    {
        void *ptr = m_curp;
        if(m_curp + size > m_endp) {
            printf("%p: overhead", m_begp);
        }
        printf("%p: reserved %u bytes, currp = %p\n", m_begp, size, m_curp);
        m_curp += size;
        return ptr;
    }

    void operator delete(void *ptr) {}

private:
    static char *m_begp, *m_curp, *m_endp;
};

template<class T>
char * pool<T>::m_begp;

template<class T>
char * pool<T>::m_curp;

template<class T>
char * pool<T>::m_endp;

struct id : pool<id>
{
    virtual ~id()
    {
        puts("~id");
    }

    virtual void show() = 0;

    static void destroy(id *p)
    {
        delete p;
    }
};

struct id_0 : id
{
    id_0(int a = 0, int b = 0, int c = 0) : a(a), b(b), c(c) {}

    virtual ~id_0()
    {
        puts("~id_0");
    }

    void show()
    {
        printf("%i %i\n", a, b);
    }

private:
    int a, b, c;
};

struct id_1 : id
{
    id_1(int a = 0, int b = 0) : a(a), b(b) {}

    virtual ~id_1()
    {
        puts("~id_1");
    }

    void show()
    {
        printf("%i %i\n", a, b);
    }

private:
    int a, b;
};

int main()
{
    id::pool_create(100500);

    vector<id *> v1{
        new id_0(), new id_1(), new id_1(10), new id_0(1, 2),
        new id_0(3, 2, 1), new id_1(1000, 200)
    };

    for_each(v1.begin(), v1.end(), mem_fun(&id::show));
    for_each(v1.begin(), v1.end(), id::destroy);

    id::pool_destroy();
    return 0;
}
numas13
()
Ответ на: комментарий от anonymous

Ничего ты не используешь и это в очередной раз говорит о твоём неосиляторстве плюсов.

Ты юзаешь указатели + банальную метаинфу к структере, которая к твоему виртуальному классу отношения не имеет.

Ты получаешь оверхед по памяти в раза 2-3 по сравнению с моим кодом( я не юзаю указатели + у меня нет метаинфы и ущербанского вектора).

Мой код сам следит за памятью - ему просто за ней следить не надо, ибо он неуязвим по определению. Мой код компактней, проще, быстрее, не даёт оверхед байт 30 на елемент и т.п.

Такой код ты не напишешь на плюсах НИКОГДА.

superhackkiller1997
()
Ответ на: комментарий от anonymous

Если ты настолько туп, что не помнишь как ты называл переменные - твои проблемы, если ты не юзал статик - твои проблемы.

Причина - твоя тупость + надуманная проблема глупцов, не более.

Пространство имён тут не причем - это написано для плюсовиков в последних стандартах не более. Это область видимости и особенность линкера.

superhackkiller1997
()
Ответ на: комментарий от superhackkiller1997

Кто ответил? Детсадовец. Мой тебе совет, пока не подучишь матчасть про всякие там памяти и прочее даже не говори. Когда ты подучишь эту самую матчасть - тогда ты поймёшь, что такое память.

По поводу указателей - твой код не проверяет выхода за границы выделенной памяти и после выделения n+1 материала у тебя закончится память.

Zodd ★★★★★
() автор топика
Ответ на: комментарий от numas13

Ну ты уже близко к вменяемомум аллокатору, потом ты поймёшь, что они не нужны и твой код будет просто не восприимчив ко всей этой мешуре.

Слишком много строк - это делается 10-ю строчками. Мне очень лень парсить такие портянки. Ненавижу этот стиль скобок. Это играние деструкторами конечно круто, но тут оно не упало.

«Пул(хотя это не пулл)» может сам следить за своими елементами - ему не нужны ассисты векторов всяких.

superhackkiller1997
()
Ответ на: комментарий от Zodd

У меня нет никакого выделения метериалов.

Давай, покажи мне, где конкретно он что-то не выделяет - я тебе объясню почему.

Вот у тебя есть выделятор памяти и у тебя есть 8гигов памяти - вот ты выделяй маллоком 8гигов и оомкиллер убьёт тебя быстрее, чем ты там что-то проверишь.

Пацан знает сколько у него памяти итак - пацану не нужны проверки, а проверками тебя запугали детсадовци и жёлтые книжонки, аля осиль с++ за 21день.

superhackkiller1997
()
Ответ на: комментарий от superhackkiller1997

Вот расскажи, что делают вот эти две строки (желательно детально).

void * pull = malloc(100500), * begin = pull;
pull = create_id0(pull, 100123, 100223, 100323);
Zodd ★★★★★
() автор топика
Ответ на: комментарий от Zodd
void * pull = malloc(100500), * begin = pull;

Тут мы маллочим 100500( я специально взял 100500 на байт 40).

Мы малочим столько, сколько нам 100% хватит.

pull = create_id0(pull, 100123, 100223, 100323);

Это аналог твоего конструктора, который берёт кастит наш указатель( ах какой я подлец - я тоже пуллом не пулл обозвал) в структуру данного типа, заполняет её и инкрементирует указатель на длинну нашей структуры, возвращая его обратно.

Т.е. после вызова функции наш pull увеличится до байта, следющего за концом нашей инициализированной структуры.

Таким макаром мы записываем последовательно наши структуры в память, а в конце ставим «флаг» END( который и является проверкой).

superhackkiller1997
()
Ответ на: комментарий от Zodd
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

typedef struct {
  uint8_t id;
  uint64_t a, b, c;
} m_id0_t;

typedef struct {
  uint8_t id;
  uint64_t a, b;
} m_id1_t;

typedef void *(*id_headler_t)(void *);

class for_lor {
public:
  for_lor(uint64_t max_size) : begin(malloc(max_size)), curr(begin), end(begin + max_size){}
  ~for_lor() {free(begin);}
  
  uint8_t add_id0(uint64_t a, uint64_t b, uint64_t c) {
    m_id0_t * p = (m_id0_t *)curr;
    p->id = 0, p->a = a, p->b = b, p->c = c;
    return ((curr = (++p)) < end);
  }
  
  uint8_t add_id1(uint64_t a, uint64_t b) {
    m_id1_t * p = (m_id1_t *)curr;
    p->id = 1, p->a = a, p->b = b;
    return ((curr = (++p)) < end);
  }
  
  void set_end() { *(uint8_t *)curr = 0xff;}
  
  void bind_headres(id_headler_t headler, uint64_t id) {headlers[id] = headler;}
  
  void call() {
    void * ptr = begin;
    do {
      ptr = headlers[*(uint8_t*)ptr](ptr);
    } while(*(uint8_t*)ptr != 0xff);
  }
private:
  void * begin, * curr, * end;
  id_headler_t headlers[2];
};

void * id0_headler(void * ptr) {
  m_id0_t * my_data = (m_id0_t *)ptr;
  fprintf(stderr, "id = %u, a = %lu, b = %lu, c = %lu\n", my_data->id, my_data->a, my_data->b, my_data->c);    
  return ++my_data;
}

void * id1_headler(void * ptr) {
  m_id1_t * my_data = (m_id1_t *)ptr;
  fprintf(stderr, "id = %u, a = %lu, b = %lu\n", my_data->id, my_data->a, my_data->b);    
  return ++my_data;
}

int main() {
  for_lor t(100500);
  t.bind_headres(id0_headler, 0);
  t.bind_headres(id1_headler, 1);
  t.add_id0(100123, 100223, 100323);
  t.add_id1(200123, 200223);
  t.set_end();
  t.call();
  return 0;
}

От мой скилл плюсов, прям рвётся на ружу. Заюзал 99% фич.

superhackkiller1997
()
Ответ на: комментарий от superhackkiller1997

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

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.