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

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

[ Новые сообщения · Игроделы · Правила · Поиск ]
  • Страница 1 из 3
  • 1
  • 2
  • 3
  • »
Форум игроделов » Программирование » C/C++ » Пару логических задач для новичков)
Пару логических задач для новичков)
vasua99Дата: Воскресенье, 22 Апреля 2012, 21:47 | Сообщение # 1
GNU follower
Сейчас нет на сайте
Code

#include <cstdio>
class A
{
   public:
     virtual void p(int n = 0) { printf("%d",n); }
};

class B : public A
{
   public:
     virtual void p(int n = 2) { printf("%d",n); }
};

int main()
{
   A* my = new B();
   my->p(); // it out "0"
   delete my;
   return 0;
}

Почему так?


Жизнь игра, и мы в ней пешки... А я кушаю пельмешки)
TimKruzДата: Воскресенье, 22 Апреля 2012, 22:02 | Сообщение # 2
старожил
Сейчас нет на сайте
Quote (vasua99)
Пару логических задач для новичков)

Я думал, что тут выложены именно задачи... wacko
Quote (vasua99)
Почему так?

Что - "так"? Почему «//it out "0"» («это выведет "0"») или что? wacko Ты конкретней пиши, что ли...


vasua99Дата: Воскресенье, 22 Апреля 2012, 22:06 | Сообщение # 3
GNU follower
Сейчас нет на сайте
прочитай интерфейсы классов А и В,а теперь вопрос,почему выводится 0,а не 2

Жизнь игра, и мы в ней пешки... А я кушаю пельмешки)
НохчиДата: Воскресенье, 22 Апреля 2012, 22:13 | Сообщение # 4
заслуженный участник
Сейчас нет на сайте
Компилятор до момента выполнения не знает, что A *my на самом деле указатель на класс B, поэтому пихает 0 в качестве аргумента.

Многие вопросы по Windows отпадут, если посмотреть тут
MatouДата: Воскресенье, 22 Апреля 2012, 23:13 | Сообщение # 5
Исходный коТ
Сейчас нет на сайте
Люблю этот язык.


ЙакудДата: Понедельник, 23 Апреля 2012, 01:28 | Сообщение # 6
участник
Сейчас нет на сайте
vasua99, дело в том, что четко указан тип объекта класса А. Т.к. метод является виртуальным, то реализация того или много виртуального метода будет определятся во время исполнения программы. Т.к. класс B наследуется от класса A, то мы имеем возможность создавать объекты с типом родителя, но не наоборот! Так вот, во время выполнения, программа видит, что используется объект класса A, следовательно вызывает его виртуальный метод.
Вот как-то так =)


"Хороший художник – копирует, гениальный – ворует!" — Pablo Picasso
.blanco 2.0


Сообщение отредактировал Йакуд - Понедельник, 23 Апреля 2012, 01:29
MatouДата: Понедельник, 23 Апреля 2012, 02:25 | Сообщение # 7
Исходный коТ
Сейчас нет на сайте
Quote (Йакуд)
Т.к. класс B наследуется от класса A, то мы имеем возможность создавать объекты с типом родителя, но не наоборот! Так вот, во время выполнения, программа видит, что используется объект класса A, следовательно вызывает его виртуальный метод.

surprised



НохчиДата: Понедельник, 23 Апреля 2012, 04:50 | Сообщение # 8
заслуженный участник
Сейчас нет на сайте
Йакуд, вызывается как раз метод класса В.

Многие вопросы по Windows отпадут, если посмотреть тут
ArchidoДата: Понедельник, 23 Апреля 2012, 05:57 | Сообщение # 9
Сэнсэй
Сейчас нет на сайте
Quote (Йакуд)
дело в том, что четко указан тип объекта класса А. Т.к. метод является виртуальным, то реализация того или много виртуального метода будет определятся во время исполнения программы. Т.к. класс B наследуется от класса A, то мы имеем возможность создавать объекты с типом родителя, но не наоборот! Так вот, во время выполнения, программа видит, что используется объект класса A, следовательно вызывает его виртуальный метод. Вот как-то так =)

Не так, выше уже написали об этом.

Дефолтные значения параметров функций компилятор ставит на основе простого анализа кода: нашел вызов функции определенного класса (в данном случае A->p(); ) и воткнул туда "0", неявно превратив код из "my->p();" в "my->p(0);".

А вызываться всегда будет функция класса B, т.к. при конструировании объекта данного класса используется именно таблица виртуальных функций класса B (здравствуй кэп) и потому, что функция "p()" переопределена в этом классе (B) - она и будет вызвана.


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

Сообщение отредактировал Archido - Понедельник, 23 Апреля 2012, 05:59
ТритонДата: Понедельник, 23 Апреля 2012, 10:26 | Сообщение # 10
постоянный участник
Сейчас нет на сайте
Quote (Йакуд)
vasua99, дело в том, что четко указан тип объекта класса А. Т.к. метод является виртуальным, то реализация того или много виртуального метода будет определятся во время исполнения программы. Т.к. класс B наследуется от класса A, то мы имеем возможность создавать объекты с типом родителя, но не наоборот! Так вот, во время выполнения, программа видит, что используется объект класса A, следовательно вызывает его виртуальный метод.
Вот как-то так =)
Бред. При номинальном типе B нельзя создать объект с фактическим типом родителя, а как раз наоборот. И так как метод виртуальный, то будет вызван метод, соответствующий фактическому типу, то есть B::p();. Но полиморфизм распространяется только на поведение, не затрагивая значения параметров по умолчанию, а номинальный тип A. Таким образом, вызывается версия метода из класса B, но со значением параметра по умолчанию, определённом в классе A.


Не всё так плохо, как оно есть на самом деле.
vasua99Дата: Понедельник, 23 Апреля 2012, 15:25 | Сообщение # 11
GNU follower
Сейчас нет на сайте
Ответ:потому что сигнатура смотрится по базовому классу,когда вызывается виртуальный метод,а значит и подставляется 0,а не 2.

Новая задача(профи не пишите!Охото услышать новичков,т.к такой вопрос могут иногда на собеседовании задать)): как не использую третью переменную,обменять значения двух переменных(я знаю только два варианта,может кто еще знает))


Жизнь игра, и мы в ней пешки... А я кушаю пельмешки)
MatouДата: Понедельник, 23 Апреля 2012, 15:44 | Сообщение # 12
Исходный коТ
Сейчас нет на сайте
Quote (vasua99)
я знаю только два варианта,может кто еще знает

Знаю я кое-кого кто знает.



ArchidoДата: Понедельник, 23 Апреля 2012, 15:51 | Сообщение # 13
Сэнсэй
Сейчас нет на сайте
Quote (vasua99)
потому что сигнатура смотрится по базовому классу,когда вызывается виртуальный метод,а значит и подставляется 0,а не 2.

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

Поэтому писать параметры по умолчанию у виртуальных функций плохой тон (даже смысла это не имеет), а если не знаешь об этой "особенности" можно убить много часов на попытку найти в чем же все таки дело biggrin Ну, в немалых проектах конечно. По хорошему компиляторы должны выдавать хотя бы warning в таких делах, но увы smile


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

Сообщение отредактировал Archido - Понедельник, 23 Апреля 2012, 16:08
SnuuxДата: Вторник, 24 Апреля 2012, 13:10 | Сообщение # 14
постоянный участник
Сейчас нет на сайте
Quote (vasua99)
Новая задача(профи не пишите!Охото услышать новичков,т.к такой вопрос могут иногда на собеседовании задать)): как не использую третью переменную,обменять значения двух переменных(я знаю только два варианта,может кто еще знает))

Так, я как раз новичек, так что мб скорее всего неправильно, но по идее, недавно читал, что это можно сделать с помощью ссылки.

P.S. Добавляй ещё задачки)
ТритонДата: Вторник, 24 Апреля 2012, 13:17 | Сообщение # 15
постоянный участник
Сейчас нет на сайте


Добавлено (24.04.2012, 13:15)
---------------------------------------------
Quote (Snuux)
что это можно сделать с помощью ссылки.
Ссылка - это только синоним некой переменной.

Добавлено (24.04.2012, 13:16)
---------------------------------------------
Quote (vasua99)
:потому что сигнатура смотрится по базовому классу,когда вызывается виртуальный метод,а значит и подставляется 0,а не 2.
Такой бред и мне не снести. Сигнатура смотрится по номинальному классу.

Добавлено (24.04.2012, 13:17)
---------------------------------------------
Quote (vasua99)
я знаю только два варианта,может кто еще знает
Интересно, какой же второй.


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

Сообщение отредактировал Тритон - Вторник, 24 Апреля 2012, 13:24
ApatiДата: Вторник, 24 Апреля 2012, 13:21 | Сообщение # 16
заслуженный участник
Сейчас нет на сайте
Quote (Тритон)
a&=b; b&=a; a&=b;

Сам-то тестировал)?
Code
#include <iostream>
int main()
{
   unsigned char a=5,b=6;
   a&=b;   
    b&=a;   
    a&=b;
   std::cout<<(int)a<<" "<<(int)b<<std::endl;
   return 0;
}

выводит: 4 4

UPD: так уже верно
Второй способ:
a+=b;
b=a-b;
a=a-b;
правда он плохой, т.к. если а и б в сумме превышают максимально допустимое значение для типа, то будет ошибка


Сообщение отредактировал Apati - Вторник, 24 Апреля 2012, 13:27
ТритонДата: Вторник, 24 Апреля 2012, 13:25 | Сообщение # 17
постоянный участник
Сейчас нет на сайте
Quote (Apati)
Сам-то тестировал)?
Подзабыл соответствия значков логическим операторам. Исправил.


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

Сообщение отредактировал Тритон - Вторник, 24 Апреля 2012, 13:25
vasua99Дата: Вторник, 24 Апреля 2012, 14:00 | Сообщение # 18
GNU follower
Сейчас нет на сайте
Ответ(ы):
Code

void swap1(int&a, int&b)
{
   a -= (b = (a += b) - b);
}

void swap2(int& a, int& b)
{
   a ^= (b ^= (a ^= b));
}


3.Напишите функцию,меняюшую рандомно местами все символы.подсказка: может использовать предыдущую функцию обмена значениями например так:
Code

void swap(char& arg1,char& arg2);
char str[] = "Hello";
swap(str[0],str[4]);
printf("%s",str); // выведет oellH

Добавлено (24.04.2012, 13:54)
---------------------------------------------
П.с все символы в строке)

Добавлено (24.04.2012, 14:00)
---------------------------------------------
И вот еще потруднее задачка среднячкам(которую я сам не решил)

Code

void swap(int& a,int& b);
char str[] = "Hello";
swap(str[0],str[4]); // str - oellH

Каким образом происходит преобразование символов при вызове функции обмена значениями,и(мне это интереснее всего) как строка не портится при этом(у мея есть предположение что при неявном преобразовани при вызове функции происходит дополнение до 4х байт(т.е 3 байта,т.к символ занимает 1 байт)из памяти в другом месте)


Жизнь игра, и мы в ней пешки... А я кушаю пельмешки)
MatouДата: Вторник, 24 Апреля 2012, 14:12 | Сообщение # 19
Исходный коТ
Сейчас нет на сайте
Quote (vasua99)
Каким образом происходит преобразование символов при вызове функции обмена значениями,и(мне это интереснее всего) как строка не портится при этом(у мея есть предположение что при неявном преобразовани при вызове функции происходит дополнение до 4х байт(т.е 3 байта,т.к символ занимает 1 байт)из памяти в другом месте)

Я несколько раз прочитал и вообще ничего не понял.



vasua99Дата: Вторник, 24 Апреля 2012, 14:29 | Сообщение # 20
GNU follower
Сейчас нет на сайте
короче смотри целый тип занимает 4 байта,а символ 1 байт, у нас есть строка (любая к примеру) тобишь массив символов.так вот при вызове функции обмена значениями (см выше) происходит неявное преобразование из ссылки на символ (который находится в массиве) в ссылку на целое.Но каким образом оно происходит?

Жизнь игра, и мы в ней пешки... А я кушаю пельмешки)
Форум игроделов » Программирование » C/C++ » Пару логических задач для новичков)
  • Страница 1 из 3
  • 1
  • 2
  • 3
  • »
Поиск:

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