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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> unresolved external symbol в *.obj при связывании, виртуальная функция в базовом классе 
V
    Опции темы
KasMP
Дата 16.7.2009, 11:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(Ошибка @  VS 2008 Express Edition)

1>Try.obj : error LNK2001: unresolved external symbol "public: virtual void __thiscall Figure::Draw(struct HWND__ *)" (?Draw@Figure@@UAEXPAUHWND__@@@Z)
1>...\Try.exe : fatal error LNK1120: 1 unresolved externals


В программе нет ничего особенного: используется самое элементарное из WinAPI, есть *.h с базовым классом (и виртуальными функциями), еще *.h с его наследниками и реализациями этих виртуальных функций, несколько *.cpp  с несложными функциями. Нигде ничего особенного не задействуется!
Основное содержание файлов, с которыми все это может быть связано:
  • Try.cpp:
    обычный файл Win32-проекта, содержащий
    Код

    BOOL InitInstance(HINSTANCE hInstance, int nCmdShow);
    LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
    ...

    Ну и его #include:
    Код

    #include "stdafx.h"
    #include "Try.h"

    #include "Draw.h"
    #include "global.h"

    #include "cl_Figure.h"
    #include "cl_Point.h"

    #include <fstream>
    using namespace std;

    Ничего серьезного в нем сейчас нет.
  • global.h
    Код

    short    scale = 60,            // нечто типа масштаба всего рисунка
            stroke = scale / 10;
    short    x_0 = 1,            // расстояние между границами клиентской области
            y_0 = 1;            // и координатной плоскостью в условных единицах
    int        x0 = scale * x_0,
            y0 = scale * y_0;
  • cl_Figure.h
    Код

    #include <fstream>
    using namespace std;

    enum        TypeOfFigure {nothing, point, line, ellipse, rectangle};
    const short    NumberOfTypes = rectangle;

    struct color {short r, g, b;};

    class Figure {
    protected:
        char    type;
        color    fpen;
    public:
        bool ValidType (char i) {
            if ((i > NumberOfTypes+'0') || (i < '0')) return false;
            return true;
        };
        Figure (ifstream *f, char ttype) {
            //*f >> fpen.r >> fpen.g >> fpen.b;
            *f >> fpen.r;
            *f >> fpen.g;
            *f >> fpen.b;
            type = ttype;};
        Figure () {type = '0'; fpen.r = fpen.g = fpen.b = 0;};
        Figure (char i) {
            if (ValidType(i)) type = i; else type = '0';
            fpen.r = fpen.g = fpen.b = 0;
        };
        Figure (char i, color j) {
            if (ValidType(i)) type = i; else type = '0';
            fpen = j;
        };
        char GetType () {return type;};
        bool SetType (char i) {
            fpen.r = fpen.g = fpen.b = 0;
            if (! ValidType(i) ) {type = 0; return false;}
            type = i;
            return true;
        };
        void SetPen (color i) {fpen = i;};
        color GetPen () {return fpen;};
        virtual void Draw (HWND hWnd);
        //virtual bool PtInFigure (POINT pt);
    };
  • cl_Point.h
    Код

    class Point : public Figure {
    protected:
        POINT    p;
    public:
        Point (ifstream *f): Figure(f,'1') {
            //*f >> p.x >> p.y;};
            *f >> p.x;
            *f >> p.y;
        };
        Point () : Figure('1') {p.x = -1; p.y = -1;};
        Point (color ppen): Figure('1',ppen) {p.x = -1; p.y = -1;};
        Point (color ppen, POINT pp): Figure('1',ppen) {p = pp;};
        void SetPoint (POINT pp) {p = pp;}; void SetX (int x) {p.x = x;}; void SetY (int y) {p.y = y;};
        void Draw (HWND hWnd);
        bool PtInFigure (POINT pt);
    };

    void Point :: Draw (HWND hWnd) {
        HDC        hdc = GetDC(hWnd);
        RECT    cl; GetClientRect(hWnd,&cl);

        HPEN    pen = CreatePen(PS_SOLID,0,RGB(fpen.r,fpen.g,fpen.b));
        HBRUSH    brush = CreateSolidBrush(RGB(fpen.r,fpen.g,fpen.b));
        HGDIOBJ    prev_pen = SelectObject(hdc,pen),
                prev_brush = SelectObject(hdc,brush);

        // координаты центра эллипса (самой точки)
        int    x = cl.left + x0+ p.x * scale,
            y = cl.bottom - y0 - p.y * scale;

        Ellipse (hdc, x-stroke, y-stroke, x+stroke, y+stroke);

        SelectObject(hdc,prev_pen); SelectObject(hdc,prev_brush);
        DeleteObject(pen); DeleteObject(brush);
    }

    bool Point :: PtInFigure (POINT pt) {
        float    r = (stroke * 1,3) ^ 2,
                rpt = ((p.x - pt.x) * (p.x - pt.x) + (p.y - pt.y) * (p.y - pt.y)) ^ 2;
        return rpt <= r;
    }
  • cl_Line.h
  • cl_FilledFigure.h
  • cl_Ellipse_Rectangle.h
  • f_Draw.cpp
    Код

    #include "stdafx.h"
    #include "draw.h"

    // рисуем оси OX, OY
    void DrawOXY (HWND hWnd) {
        RECT    cl;
        HDC        hdc;

        GetClientRect(hWnd, &cl);
        hdc = GetDC(hWnd);

        short    stroke = scale/10;    // длина черточки-разметки на ОХ и OY

        HFONT    font = CreateFont(scale*2/5,scale/10,3,0,0,0,0,0,0,0,0,0,0,0);
        HGDIOBJ    previous = SelectObject(hdc,font);

        // рисуем линии осей
        MoveToEx (hdc, cl.left+x0, cl.top+y0, NULL);
        LineTo (hdc, cl.left+x0, cl.bottom-y0);
        LineTo (hdc, cl.right-x0, cl.bottom-y0);

        // стрелочка на конце луча OY
        MoveToEx (hdc, cl.left+x0-stroke*2, cl.top+y0+stroke*2, NULL);
        LineTo (hdc, cl.left+x0, cl.top+y0);
        LineTo (hdc, cl.left+x0+stroke*2, cl.top+y0+stroke*2);

        // стрелочка на конце луча OX
        MoveToEx (hdc, cl.right-x0-stroke*2, cl.bottom-y0-stroke*2, NULL);
        LineTo (hdc, cl.right-x0, cl.bottom-y0);
        LineTo (hdc, cl.right-x0-stroke*2, cl.bottom-y0+stroke*2);

        char    s_char[3];
        short    s_short = 1;
        RECT    rhelp;

        // размечаем OY
        for (int i = cl.bottom-y0-scale, s_short = 1; i >= cl.top+y0+scale/2; s_short++, i -= scale) {
            MoveToEx (hdc, cl.left+x0-stroke, i, NULL);
            LineTo (hdc, cl.left+x0+stroke, i);

            SetRect (&rhelp, cl.left+x0-stroke*6, i-stroke*2, cl.left+x0-stroke*2, i+stroke*2);
            _itoa_s (s_short, s_char, 3, 10);
            DrawText (hdc, s_char, strlen(s_char), &rhelp, DT_SINGLELINE | DT_VCENTER | DT_CENTER);
        }

        // размечаем OX
        for (int i = cl.left+x0+scale, s_short = 1; i <= cl.right-x0-scale/2; s_short++, i += scale) {
            MoveToEx (hdc, i, cl.bottom-y0-stroke, NULL);
            LineTo (hdc, i, cl.bottom-y0+stroke);

            SetRect (&rhelp, i-stroke*2, cl.bottom-y0+stroke*2, i+stroke*2, cl.bottom-y0+stroke*6);
            _itoa_s (s_short, s_char, 3, 10);
            DrawText (hdc, s_char, strlen(s_char), &rhelp, DT_SINGLELINE | DT_VCENTER | DT_CENTER);
        }

        // ставим ноль в начале координат, подписываем лучи OX и OY
        SetRect (&rhelp, cl.left+x0-stroke*6, cl.bottom-y0+stroke*2, cl.left+x0-stroke*2, cl.bottom-y0+stroke*6);
        DrawText (hdc, "0", 1, &rhelp, DT_SINGLELINE | DT_VCENTER | DT_CENTER);

        SetRect (&rhelp, cl.left+x0-stroke*2, cl.top+y0-stroke*5, cl.left+x0+stroke*2, cl.top+y0-stroke);
        DrawText (hdc, "y", 1, &rhelp, DT_SINGLELINE | DT_VCENTER | DT_CENTER);

        SetRect (&rhelp, cl.right-x0+stroke, cl.bottom-y0-stroke*2, cl.right-x0+stroke*5, cl.bottom-y0+stroke*2);
        DrawText (hdc, "x", 1, &rhelp, DT_SINGLELINE | DT_VCENTER | DT_CENTER);

        SelectObject(hdc,previous);
        DeleteObject(font);
    }


    // рисуем координатные линии
    void DrawGrid (HWND hWnd) {
        RECT    cl;
        HDC        hdc;

        GetClientRect(hWnd, &cl);
        hdc = GetDC(hWnd);

        HPEN    pen = CreatePen(PS_DOT,1,RGB(255,0,0));
        HGDIOBJ    previous = SelectObject(hdc,pen);

        // горизонтальные координатные линии
        for (int i = cl.bottom-y0-scale; i >= cl.top+y0+scale/2; i -= scale) {
            MoveToEx (hdc, cl.left+x0, i, NULL);
            LineTo (hdc, cl.right-x0-scale/2, i);
        }

        // вертикальные координатные линии
        for (int i = cl.left+x0+scale; i <= cl.right-x0-scale/2; i += scale) {
            MoveToEx (hdc, i, cl.bottom-y0, NULL);
            LineTo (hdc, i, cl.top+y0+scale/2);
        }

        SelectObject(hdc,previous);
        DeleteObject(pen);
    }
  • Draw.h
    Код

    extern short    scale, stroke,
                    x_0, y_0;
    extern int        x0, y0;

    void DrawOXY (HWND hWnd);
    void DrawGrid (HWND hWnd);
  •  ...
Все советы из похожих тем не помогли smile smile.
P.S.. На самом деле у меня все написано очень ровно, столбик к столбику. Не знаю, почему тут все ползет во все стороны...
PM MAIL   Вверх
mes
Дата 16.7.2009, 11:49 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



Цитата(KasMP @  16.7.2009,  10:42 Найти цитируемый пост)
unresolved external symbol "public: virtual void __thiscall Figure::Draw(struct HWND__ *)"

забыла где то дать определение функции Figure::Draw, или если тело функции не нужно (т.е Figure позиционируется как абстрактный класс), сделать ее чисто виртуальной (=0;)

Добавлено через 2 минуты и 44 секунды
Цитата(KasMP @  16.7.2009,  10:42 Найти цитируемый пост)
extern short    scale, stroke,
                x_0, y_0;
extern int        x0, y0;

эти данные лучше оформить структурой Context и передавать как парамметр в функцию рисования.



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


Опытный
**


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

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



Цитата(mes @  16.7.2009,  11:49 Найти цитируемый пост)
забыла где то дать определение функции Figure::Draw, или если тело функции не нужно (т.е Figure позиционируется как абстрактный класс), сделать ее чисто виртуальной (=0;)

Действительно... Ты очень умный smile .
Моя беда в том, что я часто не дочитываю самые последние пункты главы... А ведь черным по белому написано (несколько раз!):
Цитата(Герберт Шилдт)

Кроме того, в некоторых ситуациях необходимо гарантировать, что виртуальня функция будет замещена во всех производных классах. Для этих ситуаций в языке С++ предусмотрены чисто виртуальные функции.

Цитата(Герберт Шилдт)

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

Или можно поступить хитрее - просто немного определить void Figure :: Draw (HWND hWnd) (ведь хочется на всякий случай иметь возможность создавать объекты типа Figure). Хотя, такие незначащие определения ради самих определний никому не нужны и только все запутывают.
Цитата(mes @  16.7.2009,  11:49 Найти цитируемый пост)
эти данные лучше оформить структурой Context и передавать как парамметр в функцию рисования.

Тоже хорошая мысль smile smile .
PM MAIL   Вверх
mes
Дата 16.7.2009, 13:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



Цитата(KasMP @  16.7.2009,  12:02 Найти цитируемый пост)
Моя беда в том, что я часто не дочитываю самые последние пункты главы... А ведь черным по белому написано (несколько раз!):

Это несколько другая ошибка, и возникла бы если бы ты не переопределила чистую виртуальную функцию в наследниках и попыталась бы создать объект такого типа.

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

Добавлено через 1 минуту и 28 секунд
Цитата(KasMP @  16.7.2009,  12:02 Найти цитируемый пост)
Или можно поступить хитрее - просто немного определить void Figure :: Draw (HWND hWnd) (ведь хочется на всякий случай иметь возможность создавать объекты типа Figure). Хотя, такие незначащие определения ради самих определний никому не нужны и только все запутывают.

пока да, потом поймешь что у абстрактных классов есть свои преимущества. smile


--------------------
PM MAIL WWW   Вверх
Леопольд
Дата 16.7.2009, 14:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Здесь я попытался разобраться со статической и динамической линковкой. Какие-то вопросы закрыл. Но классы не трогал.
http://forum.vingrad.ru/forum/topic-263893...y1900638/0.html

Тут есть свои тонкости: 

   inline функции не подчиняются ODR, у них свои правила; 

   static функции члены линкуются динамически, в отличие от обычных  static функций. Это значит что определения  static функций членов не следует помещать в заголовочном файле, таким образом можно нарушить ODR если сделать #include в нескольких .cpp файлах проекта (как правило, это разные единицы трансляций). А определения обычных static функций можно без проблем помещать в заголовочных файлах, тогда для каждой единицы трансляции будет свой экземпляр такой функции.
Пример:

first.h
Код

#ifndef FIRST_H
#define FIRST_H
#include <iostream>

struct first{
    static void sta_mem_fun(void);
};

static char c = 'a';

static void sta_glo_fun(void){
    std::cout<<"::sta_glo_fun() - "<<c<<std::endl;
}
#endif


first.cpp
Код

#include "first.h"

void first::sta_mem_fun(void){
        std::cout<<"first::sta_mem_fun() - "<<c<<std::endl;
}


main.cpp
Код

#include "first.h"
int main() {
    c = 'b';
    first::sta_mem_fun();  //выведет first::sta_mem_fun() - a, следовательно слинковано динамически.
    sta_glo_fun(); //выведет ::sta_glo_fun() - b, виден свой экземпляр статической переменно
}


ODR - One Definition Rule (Правило Одного Определения)

Есть и другие аспекты.

Это сообщение отредактировал(а) Леопольд - 16.7.2009, 14:49


--------------------
вопросов больше чем ответов
PM MAIL   Вверх
zim22
Дата 16.7.2009, 16:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


depict1
****


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

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



Цитата(Леопольд @  16.7.2009,  14:43 Найти цитируемый пост)
. Это значит что определения  static функций членов не следует помещать в заголовочном файле, таким образом можно нарушить ODR если сделать #include в нескольких .cpp файлах проекта

почему у меня правило ODR не нарушается? 
1) определение static функции помещено в заголовочном файле
2) сделан #include в нескольких cpp файлах проекта (Bar.cpp, main.cpp)
Код

//Foo.h
#ifndef FOO_H
#define FOO_H

struct Foo {
  inline static void fcn() {}
};

#endif // FOO_H

Код

//Bar.h
#ifndef BAR_H
#define BAR_H

struct Bar {
  void bar_fcn();
};

#endif // BAR_H

Код

// Bar.cpp
#include "Bar.h"
#include "Foo.h"

void Bar::bar_fcn() {
  Foo::fcn();
}

Код

// main.cpp
#include "Foo.h"
#include "Bar.h"

int _tmain(int argc, _TCHAR* argv[])
{
  Foo f;
  f.fcn();

  Bar b;
  b.bar_fcn();

  return 0;
}




Это сообщение отредактировал(а) zim22 - 16.7.2009, 18:09


--------------------
PM MAIL   Вверх
Леопольд
Дата 16.7.2009, 19:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(zim22 @ 16.7.2009,  16:21)
почему у меня правило ODR не нарушается? 
1) определение static функции помещено в заголовочном файле
2) сделан #include в нескольких cpp файлах проекта (Bar.cpp, main.cpp)
Код

//Foo.h
#ifndef FOO_H
#define FOO_H

struct Foo {
  inline static void fcn() {}
};

#endif // FOO_H

Потому что она inline, и не только из-за квалификатора, а ещё из-за того что определение находится в теле класса. Для inline функций свои правила. Однако, inline static функции члены всё равно, линкуются динамически в отличии от inline static обычных функций, которые линкуются статически.

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

А вроде и не наврал smile В страндарте ничего не нашёл, g++ 4.3.3 линкует всё же динамически. Перепроверил. Если подумать, то это логично. inline линкуются динамически, static функции члены тоже линкуются динамически, так почему же inline static функции члены должны линковаться статически?

Это сообщение отредактировал(а) Леопольд - 16.7.2009, 20:45


--------------------
вопросов больше чем ответов
PM MAIL   Вверх
zim22
Дата 16.7.2009, 19:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


depict1
****


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

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



Леопольд, не понимаю. где я сделал что-то не то?
Цитата(Леопольд @  16.7.2009,  14:43 Найти цитируемый пост)
 определения  static функций членов не следует помещать в заголовочном файле

я поместил:
Код

struct Foo {
  inline static void fcn() {}
};


Цитата(Леопольд @  16.7.2009,  14:43 Найти цитируемый пост)
таким образом можно нарушить ODR если сделать #include в нескольких .cpp файлах проекта

#include сделал в нескольких файлах
Код

// Bar.cpp
#include "Foo.h"

Код

// main.cpp
#include "Foo.h"

почему ODR не нарушается? вы же пишете, что таким образоем его можно нарушить.


--------------------
PM MAIL   Вверх
Леопольд
Дата 16.7.2009, 19:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(zim22 @ 16.7.2009,  19:22)
почему ODR не нарушается? вы же пишете, что таким образоем его можно нарушить.

Что именно непонятно из моего объяснения? smile Я уточню.

Попробуйте сделать так:
Код

struct Foo {
  static void fcn();
};

void Foo::fcn(){
}


Это сообщение отредактировал(а) Леопольд - 16.7.2009, 19:29


--------------------
вопросов больше чем ответов
PM MAIL   Вверх
zim22
Дата 16.7.2009, 19:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


depict1
****


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

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



Цитата(Леопольд @  16.7.2009,  19:27 Найти цитируемый пост)
Попробуйте сделать так:

сделал. всё компилится без ошибок. и в Студии, и в GCC

Цитата(Леопольд @  16.7.2009,  19:27 Найти цитируемый пост)
Что именно непонятно из моего объяснения?

мне непонятно не ваше объяснение, а ваше утверждение, что
Цитата(Леопольд @  16.7.2009,  14:43 Найти цитируемый пост)
можно нарушить ODR если сделать #include в нескольких .cpp файлах проекта

нарушьте его, прошу вас. smile
у меня не получается...  smile 


--------------------
PM MAIL   Вверх
Леопольд
Дата 16.7.2009, 19:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(zim22 @ 16.7.2009,  19:36)
нарушьте его, прошу вас. smile

first.h
Код

#ifndef FIRST_H
#define FIRST_H

struct first{
    static void sta_mem_fun(void);
};

void first::sta_mem_fun(void){
}

#endif


first.cpp
Код

#include "first.h"


main.cpp
Код

#include "first.h"
int main() {
    return 0;
}


Добавлено через 12 минут и 33 секунды
Цитата(zim22 @ 16.7.2009,  19:36)
у меня не получается...  smile

А у меня получается  smile 

Это сообщение отредактировал(а) Леопольд - 16.7.2009, 19:53


--------------------
вопросов больше чем ответов
PM MAIL   Вверх
zim22
Дата 16.7.2009, 21:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


depict1
****


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

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



 smile 
Цитата(Леопольд @  16.7.2009,  19:41 Найти цитируемый пост)
А у меня получается

я понял, что не понимаю, как линкуются программы в С++. лучше поздно, чем никогда...


--------------------
PM MAIL   Вверх
KasMP
Дата 17.7.2009, 07:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(mes @  16.7.2009,  13:11 Найти цитируемый пост)
В твоем же случае наследники роли не играют. Ты объявила функцию, а тело не написала. В обычной функции выдало бы ошибку только в том случае, если  ты где нибудь попыталась бы ее использовать, ну а в случае с виртуальной функцией всегда (так как компилятор должен занести ее адрес в специальную таблицу.)

Да, если заглянуть в переменную типа Point/Line/Ellipse/Rectangle во время выполнения, то в них появляется указатель на Draw() smile .
Цитата(mes @  16.7.2009,  13:11 Найти цитируемый пост)
пока да, потом поймешь что у абстрактных классов есть свои преимущества. 

Поскорей бы smile ...
PM MAIL   Вверх
Леопольд
Дата 17.7.2009, 08:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(KasMP @ 17.7.2009,  07:51)
Цитата(mes @  16.7.2009,  13:11 Найти цитируемый пост)
пока да, потом поймешь что у абстрактных классов есть свои преимущества. 

Поскорей бы smile ...

C# - Interface. 
C++ - abstract class.

Полезность интерфейса достаточно проста. Например, у разных авто (пожарная, скорая и т.п.) разное предназначение, но есть одинаковый интерфейс - руль, педали, кпп smile В чём то они отличаются. Как правило, абстрактный базовый класс предоставляет этот общий интерфейс к потомкам. Если функция чисто виртуальная, значит эта функция должна быть переопределена в потомке (если он сам не является интерфейсом).
Имея коллекцию указателей-интерфейсов, можно "управлять" разными объектами (с этим общим интерфейсом) на которые они указывают.
Логично и то, что нельзя создать объект абстрактного класса, ведь голый интерфес, не "подключенный" ни к чему конкретному ничем не управляет.
Как правило, множественное наследование интерфейсов не создаёт проблем. Т.е. у объекта, может быть несколько разных интерфейсов одновременно.

Это сообщение отредактировал(а) Леопольд - 17.7.2009, 11:14


--------------------
вопросов больше чем ответов
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

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

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


 




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


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

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