Модераторы: bsa

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Помогите разобраться с наследованием 
:(
    Опции темы
yngwie19
Дата 2.12.2008, 14:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 829
Регистрация: 15.6.2008
Где: Новгород

Репутация: нет
Всего: нет



Всем привет. У меня следующий вопрос. Когда мы реализуем механизм наследования, в некоторых книгах пишут, что объекты производного класса также являются объектами базового класса, однако обратное не верно. Приведите пожалуйста примеры что имеется в виду. Спасибо.
PM MAIL   Вверх
bomberman
Дата 2.12.2008, 15:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 39
Регистрация: 4.4.2008
Где: Брест

Репутация: нет
Всего: нет



Цитата(yngwie19 @  2.12.2008,  14:38 Найти цитируемый пост)
объекты производного класса также являются объектами базового класса

Так говорят, потомучто объекты производного класса содержат такие же поля как и объекты базового класса и объекты производных
классвов могут пользоваться методами, которые реализованы в базовом классе. Т.е. объект производного класса состоит из: 
объекта базового класса + своих полей и методов, 
поэтому и говорят что объект производного класса является объектом базового.

Цитата(yngwie19 @  2.12.2008,  14:38 Найти цитируемый пост)
однако обратное не верно

Обратное конечно же не верно, потомучто объект базового класса ну никак не может содержать поля производного класса,
по крайней мере потому, что базовому классу ничего не известно о существовании производного класса. 

Если надо, могу развить мысль.

PM MAIL ICQ   Вверх
mes
Дата 2.12.2008, 15:22 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 79
Всего: 250



Цитата(yngwie19 @  2.12.2008,  14:38 Найти цитируемый пост)
Всем привет. У меня следующий вопрос. Когда мы реализуем механизм наследования, в некоторых книгах пишут, что объекты производного класса также являются объектами базового класса, однако обратное не верно. Приведите пожалуйста примеры что имеется в виду. 

Любая селедка -  рыба, но далеко не каждая рыба является селедкой. © помойму Люиса Кэрола


--------------------
PM MAIL WWW   Вверх
yngwie19
Дата 2.12.2008, 19:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 829
Регистрация: 15.6.2008
Где: Новгород

Репутация: нет
Всего: нет



Спасибо за объяснения, а скажите тогда. 
Где можно использовать и зачем нужно приводить тип указатель производного класса указателю базового класса. Если можно с примерами

Это сообщение отредактировал(а) yngwie19 - 2.12.2008, 19:04
PM MAIL   Вверх
Dmi3ev
Дата 2.12.2008, 19:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1698
Регистрация: 28.11.2007

Репутация: 13
Всего: 41



Цитата

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

Немного криво написано, но если я правильно понял, то это нужно для того, чтобы в базовом классе были недоступны те функции, которые используются в производном классе (функции, которые присущи только производному классу). Как-то вот так  smile 

Это сообщение отредактировал(а) Dmi3ev - 2.12.2008, 19:26


--------------------

PM MAIL   Вверх
dsx
Дата 2.12.2008, 19:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 41
Регистрация: 7.9.2008
Где: Москва

Репутация: нет
Всего: 1



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

Например, мы создаем абстрактный класс(Область), и объявляем в нем виртуальную функцию(вычисление площади). От это класса наследуются классы Прямоугольник и Треугольник - конкретные фигуры, и там эта функция перекрывается конкретными реализациями вычисления площади. При этом, мы можем использовать указатель базового класса Область для создания объектов классов-наследников Прямоугольник и Треугольник. При вызове через этот указатель виртуальной функции подсчета площади, будет выполняться та функция, которая соответствует размещенному по этому указателю объекту. Таким образом, в интерфейсе программы мы можем не задумываться о том, объект какого из классов-наследников у нас создан - просто вызываем функцию, и она считает то, что нужно.

Описанный пример на C++
Код

#include <iostream>
#include <stdlib.h>

using namespace std;

class Area {
    protected:
        double _d1, _d2;
        Area(double d1, double d2):_d1(d1),_d2(d2) {}
    public:
        virtual void put_dim(double d1, double d2) {_d1 = d1; _d2 = d2;}
        virtual void get_dim(double &d1, double &d2) {d1 = _d1; d2 = _d2;}
        virtual double get_area() = 0;
        virtual void display_area() {cout << "area = " << get_area() << endl;}
        virtual ~Area() {cout << "Destructor Area" << endl;}
        static Area* makeRect(double d1, double d2);
        static Area* makeTria(double d1, double d2);
};

class Rectangle: public Area{
    public:
        Rectangle(double d1, double d2):Area(d1, d2) {}
        virtual double get_area() {
            cout << "Rectangle::get_area()" << endl;
            return _d1 * _d2;
        }
        virtual ~Rectangle() {cout << "Destructor Rectangle" << endl;}
};

class Triangle: public Area{
    public:
        Triangle(double d1, double d2):Area(d1, d2) {}
        virtual double get_area() {
            cout << "Triangle::get_area()" << endl;
            return _d1 * _d2 / 2;
        }
        virtual ~Triangle() {cout << "Destructor Triangle" << endl;}

};

Area* Area::makeRect(double d1, double d2) {
    Area* p = new Rectangle(d1, d2);
    return p;
}

Area* Area::makeTria(double d1, double d2) {
    Area* p = new Triangle(d1, d2);
    return p;
}

Area* gen(int i) {
    double d1 = (i * 10) / 3;
    double d2 =  d1 * 2;
    Area* p;
    switch (i%2) {
        case 0: p = Area::makeRect(d1, d2); break;
        case 1: p = Area::makeTria(d1, d2); break;
    }
    return p;
}

int main() {
    Area* p;
    for (int i = 0; i < 20; i++) {
        p = gen(i);
        p->display_area();
        delete p;
    }
    return 0;
}

PM MAIL WWW   Вверх
Annihilator
Дата 2.12.2008, 19:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


bytegrinder
**


Профиль
Группа: Участник
Сообщений: 493
Регистрация: 21.11.2006
Где: Омск

Репутация: 1
Всего: 3



Цитата(Dmi3ev @ 2.12.2008,  23:25)
Цитата

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

Немного криво написано, но если я правильно понял, то это нужно для того, чтобы в базовом классе были недоступны те функции, которые используются в производном классе (функции, которые присущи только производному классу). Как-то вот так  smile

Наоборот, надо базовый к производному привести.


--------------------
Если вы не можете сделать хоpошyю пpогpаммy, сделайте, чтобы она по кpайней меpе выглядела хоpошо
PM ICQ   Вверх
yngwie19
Дата 2.12.2008, 19:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 829
Регистрация: 15.6.2008
Где: Новгород

Репутация: нет
Всего: нет



dsx, Я понял твою мысль, а не мог бы ты привести пример попроще. Очень много кода, сложно сразу охватить.
PM MAIL   Вверх
dsx
Дата 2.12.2008, 21:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 41
Регистрация: 7.9.2008
Где: Москва

Репутация: нет
Всего: 1



Код

#include <iostream>

using namespace std;

class Human {
    public:
        virtual void say() = 0;
};

class Man: public Human {
    public:
        virtual void say() {
            cout << "I'm man" << endl;
        }
};

class Woman: public Human {
    public:
        virtual void say() {
            cout << "I'm woman" << endl;
        }
};

int main() {
    Human* human = new Man();
    human->say();
    delete human;

    human = new Woman();
    human->say();
    delete human;
}

PM MAIL WWW   Вверх
yngwie19
Дата 2.12.2008, 21:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 829
Регистрация: 15.6.2008
Где: Новгород

Репутация: нет
Всего: нет



dsx, Все теперь понятно, т.е при использовании полиморфизма мы всегда работаем через указатель на базовый абстрактный класс да? А когда динамически выделяем для него пямять, например:
Код

human = new Man()

то здесь происходит неявное преобразование  (Human*)Man, так?
P.S: Кстати зачем скобки после Man и Woman ?
PM MAIL   Вверх
mes
Дата 2.12.2008, 22:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 79
Всего: 250



вот пример с использованием и понижающего и повышающего преобразования :
Код

#include <iostream>
#include <vector>

class Auto
{
    public:
        virtual ~Auto() {};
        friend std::ostream& operator << (std::ostream&, const Auto&); // глобальный оператор <<, который вызовет виртуальную функцию  PrintMe 
    protected:
        virtual void PrintMe (std::ostream& o) const=0; // виртуальная функция для вывода информации об объекте
};

std::ostream& operator << (std::ostream& o, const Auto& a)
{
    a.PrintMe(o); 
    return o;
};

class Bmw : public Auto
{
    public:
    protected:
        virtual void PrintMe (std::ostream& o) const { o<<"Bmw"; };

};
class Audi : public Auto
{
    public:
    protected:
        virtual void PrintMe (std::ostream& o) const { o<<"Audi"; };

};

class Tank : public Auto
{
    public:
        void Fire (std::ostream& o) const { o << "FIRE"; } // не виртуальная функция, которой к тому же нет у класса Auto
    protected:
        virtual void PrintMe (std::ostream& o) const { o<<"Tank"; };

};

class MyTank : public Tank
{
    protected:
        virtual void PrintMe (std::ostream& o) const { o<<"MyTank"; };

};

void SimpleCout (const Auto* a)
{
    std::cout<< (*a) << std::endl; // просто построчный вывод.
};

void FireIfTank (const Auto* a)
{
    std::cout<< (*a) << " "; // вывод (имени) объекта
    if (const Tank *tank = dynamic_cast<const Tank*>(a)) // приводим указатель на Auto к указателю на Tank и если удачно
                                             { tank->Fire(std::cout); } // вызываем  функцию потомка, которой нет у базового класса.
    std::cout<<std::endl;
};

void DeleteObj (Auto *a) /// просто удаление
{
    delete a;
}

int main()
{

  std::vector <Auto *> v;  // массив объектов производных от класса Auto

  v.push_back (new Bmw);  // заполняем массив разными машинами на свой вкус.
  v.push_back (new Bmw);
  v.push_back (new Audi);
  v.push_back (new Tank);
  v.push_back (new Bmw);
  v.push_back (new Audi);
  v.push_back (new MyTank);
  v.push_back (new Tank);
  v.push_back (new Audi);

  std::cout << "list of autos:"<<std::endl;  
  for_each (v.begin(), v.end(), &SimpleCout); для каждого элемента масива применяем функцию SimpleCout
  std::cout<<std::endl;

  std::cout << "list of autos & fire if tank:"<<std::endl;
  for_each (v.begin(), v.end(), FireIfTank ); // для каждого элемента масива применяем функцию FireIfTank 
  std::cout<<std::endl;

  for_each (v.begin(), v.end(), DeleteObj );// удаляем наши объекты, после наш массив невалиден
  v.clear();// очищаем масив.

  system("pause");
  return 0;
}



Это сообщение отредактировал(а) mes - 2.12.2008, 23:53


--------------------
PM MAIL WWW   Вверх
yngwie19
Дата 2.12.2008, 22:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 829
Регистрация: 15.6.2008
Где: Новгород

Репутация: нет
Всего: нет



mes, спасибо за пример, это пока сложно для меня, ответь пожалуйста на последний вопрос который я задал
PM MAIL   Вверх
mes
Дата 2.12.2008, 23:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 79
Всего: 250



Цитата(yngwie19 @  2.12.2008,  22:19 Найти цитируемый пост)
mes, спасибо за пример, это пока сложно для меня, ответь пожалуйста на последний вопрос который я задал 

Цитата(yngwie19 @  2.12.2008,  21:58 Найти цитируемый пост)
P.S: Кстати зачем скобки после Man и Woman ? 

этот ? считайте, что для красоты ) 

Цитата(yngwie19 @  2.12.2008,  22:19 Найти цитируемый пост)
это пока сложно для меня, 

добавил комментарии



Это сообщение отредактировал(а) mes - 2.12.2008, 23:36


--------------------
PM MAIL WWW   Вверх
J0ker
Дата 3.12.2008, 00:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 986
Регистрация: 17.9.2008

Репутация: 9
Всего: 14



Цитата(mes @ 2.12.2008,  23:28)
Цитата(yngwie19 @  2.12.2008,  21:58 Найти цитируемый пост)
P.S: Кстати зачем скобки после Man и Woman ? 

этот ? считайте, что для красоты ) 

наличие и отсутствие скобок имеет значение для PODS/POD типов - наличие означает инициализация дефолтным констрактором, отсутствие - отсутствие инициализации
т.е.
Код

int *pi1 = new int; // по адресу pi1 мусор
int *pi2 = new int(); // по адресу pi2 0


Это сообщение отредактировал(а) J0ker - 3.12.2008, 00:16


--------------------
user posted image
PM MAIL   Вверх
yngwie19
Дата 3.12.2008, 01:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 829
Регистрация: 15.6.2008
Где: Новгород

Репутация: нет
Всего: нет



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

Код

human = new Man()

 то здесь происходит неявное преобразование  (Human*)Man, так?


 
 

PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0566 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.