Вторник, 19 Марта 2024, 12:19

Приветствую Вас Гость

[ Новые сообщения · Игроделы · Правила · Поиск ]
  • Страница 3 из 3
  • «
  • 1
  • 2
  • 3
Форум игроделов » Программирование » C/C++ » Пару логических задач для новичков)
Пару логических задач для новичков)
ArchidoДата: Пятница, 27 Апреля 2012, 08:13 | Сообщение # 41
Сэнсэй
Сейчас нет на сайте
Тритон
Хех, ты вообще пишешь немного о чем-то своем happy , при чем не только в этой теме...

Изначально вопрос состоял в том, что приведение ссылок вообще невозможно. При чем это были твои слова. Речи небыло о том, хорошо это или плохо.
Итак приведение в С++ возможно с чего угодно и на что угодно. Как оно там работает, хорошо это или плохо - это уже отдельная песня. Скажу только, что если понимать как оно работает - то никаких проблем с использованием таких вещей не будет. Целесообразность - отдельный вопрос, который тут не обсуждается.

Quote (Тритон)
Хорошо, допустим строка у тебя длинная и за границу ты не выйдешь

Если и выйду, то ничего не будет абсолютно. Инфа 100%

Quote (Тритон)
Но функция то значение отдельного байта всё равно уже не способна ни прочитать, ни записать

Все можно:
Code

void swap(int &a, int &b) {
     char &x = *((char*)&a + 1);
     x = '7';
}


Quote (Тритон)
аргументы у тебя - байты

Аргументы - всегда байты biggrin

Quote (Тритон)
Уж если свопишь подстроки, то выглядеть это должно иначе

Я не своплю подстроки, я своплю два символа. Ты до сих пор не понимаешь как работает это конструкция: "a ^= (b ^= (a ^= b & 0xFF) & 0xFF) & 0xFF".
Говорить больше не о чем.

Quote (Тритон)
нельзя хитрить с регистрами

Где и кто хитрит с регистрами? biggrin Или кто собирается это делать?

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

P.S. У тебя большая каша в голове и ты "выкладываешь" эту кашу фактически в каждой обсуждаемой теме, при этом не очень хорошо разбираясь, собственно, в вопросах этой темы. Стоит чуток об этом подумать.


C++ - он особенный. С помощью него можно не только выстрелить себе в ногу, но и повеситься в пустой комнате:)
ТритонДата: Пятница, 27 Апреля 2012, 09:01 | Сообщение # 42
постоянный участник
Сейчас нет на сайте
Quote (Archido)
Все можно:
Code

void swap(int &a, int &b) {
char &x = *((char*)&a + 1);
x = '7';
}

При этом ты затрёшь нолями ещё 3 байта. Если они и были по нолям, то всё в порядке. А если нет?

Добавлено (27.04.2012, 09:01)
---------------------------------------------
Quote (Archido)
Ты до сих пор не понимаешь как работает это конструкция: "a ^= (b ^= (a ^= b & 0xFF) & 0xFF)
Ещё смешней. Когла читаешь
Code
void swap(int &a, int &b);
, то за ним представляешь
Code
void swap(int &a, int &b)
{
    int t;
    t=a;
    a=b;
    b=t;
}
, действительная реализация должна быть эквивалентно. Если же на самом деле будет
Code
void swap(int &a, int &b)
{
    int t;
    t=a;
    a=(b&0x000000FF)|(a&0xFFFFFF00);
    b=(t&0x000000FF)|(b&0xFFFFFF00);
}
, то счастливой отладки функции
Code
void sort(int *data, int n)
{
    int *i;
    int *j;
    int *e;
    e=data+n-1;
    for (i=data; i<e; ++i)
    {
      for (j=i+1; j<=e; ++j)
      {
       if (*i<*j)
       {
        swap(*i,*j);
       }
      }
    }
}
. Порча дважды противоположными образами - не лучшее решение. Своп байтов должен выглядеть, как своп байтов. Зачем приводить байты к адресам двойных слов, чтоб сразу же не явно приводить их к адресам снова байтов?


Не всё так плохо, как оно есть на самом деле.

Сообщение отредактировал Тритон - Пятница, 27 Апреля 2012, 09:06
warzesДата: Пятница, 27 Апреля 2012, 09:44 | Сообщение # 43
участник
Сейчас нет на сайте
блин, какие здесь умники собрались. Первая задача вообще вредная и до сих пор не дан ответ почему так. Поэтому я обязан здесь оставить вот это
Code

#include <cstdio>  
  class A  
  {  
    public:  
      virtual void p(int n=4) { printf("%d",n); }  
  };  
   
  class B : public A  
  {  
    public:  
      virtual void p(int n=4) { printf("%d",n+1); }  
  };  
   
  int main()  
  {  
    A* my = new B();  
    my->p();  
    delete my;  
    return 0;  
  }

На экране будет 5 а не 4. Так что топик стартер - зачем ты новичков вводишь в заблуждение этим:
Quote

Ответ:потому что сигнатура смотрится по базовому классу,когда вызывается виртуальный метод,а значит и подставляется 0,а не 2.

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


Мой блог
Вики DirectX
ArchidoДата: Пятница, 27 Апреля 2012, 09:54 | Сообщение # 44
Сэнсэй
Сейчас нет на сайте
Тритон
Ох, ты меня вообще похоже не слышишь... Как же это сложно.

Quote (Тритон)
При этом ты затрёшь нолями ещё 3 байта. Если они и были по нолям, то всё в порядке. А если нет?

Code

void Replace (int &arg) {
          char &x = *((char*)&arg + 0);
          x = 'W';
}

char str[] = "<+>";        
Replace( (int&) str[1]);
std::cout << str;  //str = "<W>";

И где я их затер? Можешь даже в отладчике посмотреть последний байт параметра arg, он каким был - таким и остался.

О чем ты вообще пишешь? Прочитай мой предыдущий пост внимательно, хотя... придется наверное повторить на пальцах:
Ты утверждал: "приведение к ссылке на другой размер вообще не возможно". На, что я тебе привел работающий пример, который делает каст сылки одного типа на другой, при этом, выполняя все тот же своп 2-х символов (а не 8-ми) без каких либо последствий. Точка. Дальнейшее бесмысленное обсуждение никакого значения не имеет. Вопрос закрыт.

vasua99
Давай еще задач для "новичков" wink , а то мы бестолково топчимся на одном месте sad

warzes
Quote (warzes)
Первая задача вообще вредная и до сих пор не дан ответ почему так

Давно уже ответили biggrin . Правильнее вообще так:
Code

#include <cstdio>      
      class A      
      {      
        public:      
          virtual void p(int n=10) { printf("%d",n); }      
      };      
           
      class B : public A      
      {      
        public:      
          virtual void p(int n=20) { printf("%d",n+1); }      
      };      
           
      int main()      
      {      
        A* my = new B();      
        my->p();      
        delete my;      
        return 0;      
      }


C++ - он особенный. С помощью него можно не только выстрелить себе в ногу, но и повеситься в пустой комнате:)

Сообщение отредактировал Archido - Пятница, 27 Апреля 2012, 10:10
warzesДата: Пятница, 27 Апреля 2012, 11:48 | Сообщение # 45
участник
Сейчас нет на сайте
Quote (Archido)
Давно уже ответили . Правильнее вообще так:

будет 10... Почему будет 10 (то есть выполнится A::p())? И почему в моем примере выполнится не A::p() а как раз таки B::p()
Я специально привел такой код чтобы показать нестабильность представленного здесь ответа, если он был правильный то получается что этот код:
Code

#include <cstdio>    
    class A    
    {    
      public:    
        virtual void p(int n=4) { printf("%d",n); }    
    };    
       
    class B : public A    
    {    
      public:    
        virtual void p(int n=4) { printf("%d",n+1); }    
    };    
       
    int main()    
    {    
      A* my = new B();    
      my->p();    
      delete my;    
      return 0;    
    }

является исключением? Вот что я имел ввиду под "не вводите новичков в заблуждение неправильными выводами"

...
Судя по тому что ты скопипастил с ошибкой, ты не обратил внимание на n+1 - { printf("%d",n+1); }   в методе B::p. То есть получилось так - если значения по умолчанию разные то выполняется A::p. А вот если они одинаковые (как у меня) - то выполняется уже B::p. так что я пока не увидел здесь ответа на вопрос...


Мой блог
Вики DirectX


Сообщение отредактировал warzes - Пятница, 27 Апреля 2012, 11:54
ArchidoДата: Пятница, 27 Апреля 2012, 12:08 | Сообщение # 46
Сэнсэй
Сейчас нет на сайте
warzes
Советую для начала скомпилить мой код, посмотреть на результат и удивиться.
Потом пройтись отладчиком и посмотреть - функция какого класса вызывается и с каким параметром. Далее подумать. После этих процедур уже можно и поумничать happy

P.S. Результатом там будет 11, а не 10.


C++ - он особенный. С помощью него можно не только выстрелить себе в ногу, но и повеситься в пустой комнате:)
ТритонДата: Пятница, 27 Апреля 2012, 15:26 | Сообщение # 47
постоянный участник
Сейчас нет на сайте
Quote (Archido)
О чем ты вообще пишешь?
О том, что нельзя писать: "Возьми синюю краску в банке с красной этикеткой, преврати её в белую и крась по верх бесцветного лака", да ещё и разбрасывать все эти цвета по десяти томам текста. Читать будет тяжко. Само же "приведение"
Code
char x;
f((int &)x);
означает: "Впихни не впихуемое". При этом будет снесена нафиг граница ячейки, что уже чревато. Так делать нельзя, а первая же попытка выполнить внутри "в лоб" любое присваивание затрёт часть данных.
Code
void f(char &x);
...
char s[]="123456789";
f(s[3]);
...
void f(int &x)
{
    x=(int)'R';
}
даст строку "123R\0\0\089". Зачем извращаться и писать
Code
x=((int)'R')|(x&0x00FFFFFF);
? Сначала грузим легковушку на платформу для перевозки 42-х тонного зеркала телескопа БТА, потом провозим её на этой платформе через ворота, рассчитанные на проезд легковушки, сносим их нафиг и заново строим, вместо того, чтоб нормально проехать своим ходом. Зачем? Провезти же легковушку таким способом через расситанные на неё ворота без их сноса не возможно.

Добавлено (27.04.2012, 15:26)
---------------------------------------------
Нохчи, Archido, я сам способен написать ещё и не такое пособие, как делать не надо. Причём, оно будет работать правильно.


Не всё так плохо, как оно есть на самом деле.

Сообщение отредактировал Тритон - Пятница, 27 Апреля 2012, 15:42
ArchidoДата: Пятница, 27 Апреля 2012, 15:40 | Сообщение # 48
Сэнсэй
Сейчас нет на сайте
Тритон
Молочик! Пиши исчо! wink

А вот кстати, что есть в С++ стандарте по поводу параметров по умолчанию и виртуальных функций:

Так, что это нормальное явление smile , правда совсем не очевидное... Поэтому не пишите параметры по умолчанию у виртуальных функций wink


C++ - он особенный. С помощью него можно не только выстрелить себе в ногу, но и повеситься в пустой комнате:)
ТритонДата: Пятница, 27 Апреля 2012, 15:44 | Сообщение # 49
постоянный участник
Сейчас нет на сайте
Code
void gauss(double *a, double *b, double *x, int n)
{
            double *i;
            double *j;
            double *k;
            double  z;
            double  s;
            for (i=a; i<=a+(n-2)*n; i+=n)
            {
             for (j=i+n; j<=a+(n-1)*n; j+=n)
             {
              z=*j/*i;
              *j=0.0;
              for (k=j+1; k<j+n; ++k)
              {
               *j-=(*i)*z;
              }
              b[(j-a)/n]-=b[(i-a)/n]*z;
             }
            }
            for (i=a+(n-1)*n; i>=a; i-=n)
            {
             s=0.0;
             for (k=i+1; k<i+n; ++k)
             {
              s+=(*k)*(x[(k-a)/n]);
             }
             x[(i-a)/n]=(b[(i-a)/n]-s)/(*i);
            }
}
Это решение системы уравнений методом Гаусса, но коэффициенты системы передаются в линейном массиве. Но так делать не надо, потому что не споткнуться на таком тексте способны только автор и компилятор, но не тот человек, который будет читать это в чужой проге и разобраться то разберётся, но время потратит. И после собственного текста только со скаляром и тремя линейными массивами я буду утверждать, что метод Гаусса требует матрицу коэффициентов, а применить его к линейному массиву коэффициентов не возможно. В данном же примере аргумент a - неявная матрица.

Добавлено (27.04.2012, 15:44)
---------------------------------------------
Quote (Archido)
вот кстати, что есть в С++ стандарте по поводу параметров по умолчанию и виртуальных функций:
Под твоим спойлером как раз иллюстрация того, то сигнатура берётся по номинальному классу.


Не всё так плохо, как оно есть на самом деле.

Сообщение отредактировал Тритон - Суббота, 28 Апреля 2012, 06:27
ArchidoДата: Пятница, 27 Апреля 2012, 15:48 | Сообщение # 50
Сэнсэй
Сейчас нет на сайте
Quote (Тритон)
Под твоим спойлером как раз иллюстрация того, то сигнатура берётся по номинальному классу.

И чо?

Added:
Всякие "сигнатуры", "номинальные классы", тема то для новичков smile , так, что давай на пальцах wink


C++ - он особенный. С помощью него можно не только выстрелить себе в ногу, но и повеситься в пустой комнате:)

Сообщение отредактировал Archido - Пятница, 27 Апреля 2012, 15:52
ТритонДата: Суббота, 28 Апреля 2012, 06:23 | Сообщение # 51
постоянный участник
Сейчас нет на сайте
В одну телегу впрячь нельзя коня и трепетную лань и ламброджина с тягачом не помещаются на общем шасси. Не впихуемое впихнуть можно, но только с разрушениями. Зачем сначала этим заниматься, а потом восстанавливать? И уж тем более ни одному компилятору не придёт в камень приводить символы к длинным интам не явно.

Добавлено (28.04.2012, 06:23)
---------------------------------------------
Quote (Archido)
Всякие "сигнатуры", "номинальные классы", тема то для новичков , так, что давай на пальцах
Куда уж пальцее для виртуальных то функций? Номинальный - это как объявлен объект, или указатель, если в декларации указан базовый, то он совпадает с номинальным, если в декларации указан его потомок, то номинальный уже он, а сигнатуры - это синтаксисы вызовов виртуальных функций. Что сложного? Можно даже не начинать писать, но если краем уха слышал о декларациях данных, иерархии классов и о том, как вообще вызываются функции, то уже должно быть понятно, но сами виртуальные функции могу быть хоть как то понятны разве что новичку в их использовании, но не тому, кто начинает учить основные операторы и программирование линейных алгоритмов. А раз добрался до виртуальных функций, значит иерархию с декларациями может сам рассказать. Попробуй новичку на пальцах рассказать о разработке языков. Не поймет, как ни старайся и сколь простую лексику при этом ни используй. Не поймёт потому, что сама тема разработки языков не новичковая.


Не всё так плохо, как оно есть на самом деле.

Сообщение отредактировал Тритон - Среда, 02 Мая 2012, 15:27
Форум игроделов » Программирование » C/C++ » Пару логических задач для новичков)
  • Страница 3 из 3
  • «
  • 1
  • 2
  • 3
Поиск:

Все права сохранены. GcUp.ru © 2008-2024 Рейтинг