С Новым годом! Форум программистов, компьютерный форум, киберфорум
C++ Builder
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.86/7: Рейтинг темы: голосов - 7, средняя оценка - 4.86
3 / 3 / 0
Регистрация: 10.06.2016
Сообщений: 417

Создание универсальной функции вывода

26.09.2016, 09:01. Показов 1568. Ответов 17

Студворк — интернет-сервис помощи студентам
У меня есть две функции: одна выводит изображение на экран, а вторая его распечатывает.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//Окружность на принтер
void F1Print(TPrinter *Prn, double x, double y, double d, double ku)
{
  //Толщина пера
  Prn->Canvas->Pen->Width=0.5*ku+0.5;
 
  //Рисование окружности
  Prn->Canvas->Ellipse((x-d/2)*ku, (y-d/2)*ku, (x+d/2)*ku, (y+d/2)*ku);
}
//--------------------------------------------------------------------
//Окружность на экран
void TForm1::F1(TImage *Image1, double x, double y, double d, double ku)
{
  //Толщина пера
  Image1->Canvas->Pen->Width=0.5*ku+0.5;
 
  //Рисование окружности
  Image1->Canvas->Ellipse((x-d/2)*ku, (y-d/2)*ku, (x+d/2)*ku, (y+d/2)*ku);
}
Так как внутри функций код почти одинаковый, то нужно сделать универсальную функцию.
Создаю класс (записываю его в dat.h):
C++
1
2
3
4
5
6
7
8
//Класс вывода графики на экран/принтер
class Graf
{
private:    // User declarations
public:     // User declarations
    //Окружность на экран/принтер
    F1(HANDLE *xxx, double x, double y, double d, double ku);
};
Описываю функцию F1 в dat.cpp:
C++
1
2
3
4
5
6
7
8
9
//Окружность на экран/принтер
void Graf::F1(HANDLE *xxx, double x, double y, double d, double ku)
{
  //Толщина пера
  xxx->Canvas->Pen->Width=0.5*ku+0.5;
 
  //Рисование окружности
  xxx->Canvas->Ellipse((x-d/2)*ku, (y-d/2)*ku, (x+d/2)*ku, (y+d/2)*ku);
}
Начинаю использовать функцию (в Unit1.cpp), для начала вывод графики на экран:
(в форме имеется компонент Image1)
C++
1
2
3
4
5
6
#include "dat.h"
void __fastcall TForm1::FormCreate(TObject *Sender)
{
  double x=50.0, y=50.0, d=20.0, ku=3.4;
  Graf->F1(Image1, x, y, d, ku);
}
Получаем ошибку: E2108 Improper use of typedef 'Graf'
Почему компилятор решил, что я неправильно использую оператор typedef 'Graf', ведь это класс?
Где я мог ошибиться?
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
26.09.2016, 09:01
Ответы с готовыми решениями:

Создание функции для вывода нескольких значений (массива)?
Создал функцию которая должна возвращать массив данных. Внутри функции все нормально работает, все необходимые данные преобразуются в...

Создание универсальной функции
Добрый день есть код js, который создает выпадающий список для инпута с определённым id <form> Упаковка: <input...

Создание универсальной функции для работы с элементом управления DataGridView
Здравствуйте, Я работаю на своей любительской программой в целях обучения. На форме 2 DataGridView. В коде много раз повторяются одни и...

17
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
26.09.2016, 14:43
Сначала надо содать объект Graf (но только с другим именем) и только потом его использовать:
C++
1
2
3
4
5
6
7
8
#include "dat.h"
void __fastcall TForm1::FormCreate(TObject *Sender)
{
  double x=50.0, y=50.0, d=20.0, ku=3.4;
  Graf graf = new Graf;
  graf->F1(Image1, x, y, d, ku);
  delete graf;
}
Это первое. Второе это то, что у Вас ошибки при создании класса Graf. Тут надо добавить void и изменить HANDLE на TImage:
C++
1
void F1(TImage *xxx, double x, double y, double d, double ku);
Третье это то, что объект типа HANDLE не знает что такое Canvas. Может надо так:
C++
1
2
3
4
5
6
7
8
9
//Окружность на экран/принтер
void Graf::F1(TImage*xxx, double x, double y, double d, double ku)
{
  //Толщина пера
  xxx->Canvas->Pen->Width=0.5*ku+0.5;
 
  //Рисование окружности
  xxx->Canvas->Ellipse((x-d/2)*ku, (y-d/2)*ku, (x+d/2)*ku, (y+d/2)*ku);
}
0
3 / 3 / 0
Регистрация: 10.06.2016
Сообщений: 417
26.09.2016, 16:07  [ТС]
Цитата Сообщение от d7d1cd Посмотреть сообщение
Graf graf = new Graf;
Во-первых, вместо этой строки нужно:
C++
1
2
char buffer[sizeof(Graf)];
  Graf *graf = new (buffer) Graf;
Во-вторых, вместо HANDLE нельзя TImage, так как цель достигнута не будет, ведь надо ещё и на принтер выводить.
0
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
26.09.2016, 16:29
Цитата Сообщение от Инженер_3 Посмотреть сообщение
Во-вторых, вместо HANDLE нельзя TImage
Инженер_3, как я посмотрю, Вы сами шибко умны. Будьте добры, снизойдите с высоты Вашего профессионализма и покажите честному народу как Вы собираетесь заставить работать вот этот код:
C++
1
2
3
4
5
void Graf::F1(HANDLE *xxx, double x, double y, double d, double ku)
{
  xxx->Canvas->Pen->Width=0.5*ku+0.5;
  xxx->Canvas->Ellipse((x-d/2)*ku, (y-d/2)*ku, (x+d/2)*ku, (y+d/2)*ku);
}
Добавлено через 2 минуты
Цитата Сообщение от Инженер_3 Посмотреть сообщение
Во-первых, вместо этой строки нужно:
C++
1
2
char buffer[sizeof(Graf)];
Graf *graf = new (buffer) Graf;
Я ошибся немного. Надо так:
C++
1
Graf *graf = new Graf;
Зачем Вы делаете так, как у Вас, я не понимаю...
0
3 / 3 / 0
Регистрация: 10.06.2016
Сообщений: 417
26.09.2016, 16:46  [ТС]
Этот код (см. ниже) не работает:
C++
1
2
3
4
5
void Graf::F1(HANDLE *xxx, double x, double y, double d, double ku)
{
  xxx->Canvas->Pen->Width=0.5*ku+0.5;
  xxx->Canvas->Ellipse((x-d/2)*ku, (y-d/2)*ku, (x+d/2)*ku, (y+d/2)*ku);
}
TImage вместо HANDLE не пойдёт, т.к. нужно ещё и на принтер выводить.
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33371 / 21497 / 8234
Регистрация: 22.10.2011
Сообщений: 36,893
Записей в блоге: 12
26.09.2016, 16:49
Цитата Сообщение от d7d1cd Посмотреть сообщение
как Вы собираетесь заставить работать вот этот код
Легко:
C++
1
2
3
4
5
6
7
class Graf
{
private:    // User declarations
public:     // User declarations
    template <class Canv>
    void F1(Canv* xxx, double x, double y, double d, double ku);
};
C++
1
2
3
4
5
6
7
8
9
10
11
12
template <class Canv>
void Graf::F1(Canv* xxx, double x, double y, double d, double ku)
{
  xxx->Canvas->Pen->Width=0.5*ku+0.5;
  xxx->Canvas->Ellipse((x-d/2)*ku, (y-d/2)*ku, (x+d/2)*ku, (y+d/2)*ku);
}
 
// вызов:
  double x=50.0, y=50.0, d=20.0, ku=3.4;
  Graf *graf = new Graf;
  graf->F1(Image1, x, y, d, ku);
  delete graf;
Аналогично и с
C++
1
graf->F1(Printer(), x, y, d, ku);
0
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
26.09.2016, 16:54
volvo, в Вашей способности заставить работать код я не сомневаюсь. Хотелось бы версию Инженер_3 услышать.
0
 Аватар для Maluda
1280 / 598 / 116
Регистрация: 18.08.2009
Сообщений: 832
26.09.2016, 16:55
Лучший ответ Сообщение было отмечено Black Fregat как решение

Решение

Инженер_3, не надо в вашем случае никаких классов

C++
1
2
3
4
5
6
7
8
// рисуем эллипс на канве
void CustomDrawEllipse(TCanvas *ACanvas, double x, double y, double d, double ku) {
    //Толщина пера
    ACanvas->Pen->Width = 0.5 * ku + 0.5;
 
    //Рисование окружности
    ACanvas->Ellipse((x - d / 2) * ku, (y - d / 2) * ku, (x + d / 2) * ku, (y + d / 2) * ku);
}
0
3 / 3 / 0
Регистрация: 10.06.2016
Сообщений: 417
27.09.2016, 11:58  [ТС]
volvo, Не работает, выдаёт ошибку:
[Linker Error] Unresolved external 'void Graf::F1<Extctrls::TImage>(Extctrls::TIm age *,
double, double, double, double)'referenced from C:\PROGRAM FILES\BORLAND\...
0
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
27.09.2016, 12:25
Цитата Сообщение от Инженер_3 Посмотреть сообщение
Не работает, выдаёт ошибку:
[Linker Error] Unresolved external 'void Graf::F1<Extctrls::TImage>(Extctrls::TIm age *,
double, double, double, double)'referenced from C:\PROGRAM FILES\BORLAND\...
Это от того, что есть описание функции, но нет реализации.
Файле h должно быть:
C++
1
2
3
4
5
6
7
class Graf
{
private:    // User declarations
public:     // User declarations
    template <class Canv>
    void F1(Canv* xxx, double x, double y, double d, double ku);
};
В файле cpp:
C++
1
2
3
4
5
6
template <class Canv>
void Graf::F1(Canv* xxx, double x, double y, double d, double ku)
{
  xxx->Canvas->Pen->Width=0.5*ku+0.5;
  xxx->Canvas->Ellipse((x-d/2)*ku, (y-d/2)*ku, (x+d/2)*ku, (y+d/2)*ku);
}
0
3 / 3 / 0
Регистрация: 10.06.2016
Сообщений: 417
27.09.2016, 13:39  [ТС]
d7d1cd, всё один к одному прописал, но не работает.
Я даже взял классический пример:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//Прототип: шаблон sort объявлен, но не определён - в dat.h
template< typename T > 
void sort( T array[], int size ); 
 
//Объявление и Определение - в dat.cpp
template< typename T >
void sort( T array[], int size )
{
  T t;
  for (int i = 0; i < size - 1; i++)
  {
    for (int j = size - 1; j > i; j--)
    {
      if (array[j] < array[j-1])
      {
        t = array[j];
        array[j] = array[j-1];
        array[j-1] = t;
      }
    }
  } 
}
 
//Вызов шаблонной функции - в Unit1.cpp
int i[5] = { 5, 4, 3, 2, 1 };
sort< int >( i, 5 );
И этот пример выдаёт такую же ошибку.
У меня сложилось мнение, что не везде эти шаблоны поддерживаются.
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33371 / 21497 / 8234
Регистрация: 22.10.2011
Сообщений: 36,893
Записей в блоге: 12
27.09.2016, 13:46
Инженер_3, я проверял на BCB6, нормально работает код. Уж где еще должно поддерживаться-то?
0
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
27.09.2016, 13:48
Инженер_3, прикрепи сюда тестовый проект, где возникает твоя ошибка.
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33371 / 21497 / 8234
Регистрация: 22.10.2011
Сообщений: 36,893
Записей в блоге: 12
27.09.2016, 13:50
Лучший ответ Сообщение было отмечено Инженер_3 как решение

Решение

Цитата Сообщение от Инженер_3 Посмотреть сообщение
//Объявление и Определение - в dat.cpp
Цитата Сообщение от Инженер_3 Посмотреть сообщение
//Вызов шаблонной функции - в Unit1.cpp
Вот она, проблема. Перенеси реализацию в Unit1.cpp, и посмотри, что будет
1
3 / 3 / 0
Регистрация: 10.06.2016
Сообщений: 417
27.09.2016, 14:06  [ТС]
Цитата Сообщение от d7d1cd Посмотреть сообщение
Инженер_3, прикрепи сюда тестовый проект, где возникает твоя ошибка.
Боюсь спросить, а "тестовый проект" это что?
Вот мои файлы:
Unit1.cpp
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <vcl.h>
#include <math.h>
#include <stdio.h>
#include <dos.h>
#include <conio.h>
#include <fstream.h>
#include <Printers.hpp>
#pragma hdrstop
 
#include "Unit1.h"
#include "dat.h"
//------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
}
//------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
  double x=50.0, y=50.0, d=20.0, ku=3.4;
  Graf *graf = new Graf;
  graf->F1(Image1, x, y, d, ku);
  delete graf;
 
  // ВЫДАЁТ ОШИБКУ:
  //[Linker Error] Unresolved external 'void Graf::F1<Extctrls::TImage>(Extctrls::TImage *,
  // double, double, double, double)'referenced from C:\PROGRAM FILES\BORLAND\...
}
dat.cpp
C++
1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream.h>
#include <vcl.h>
#include <math.h>
#include <fstream.h>
#include "dat.h"
 
template <class Canv>
void Graf::F1(Canv* xxx, double x, double y, double d, double ku)
{
  xxx->Canvas->Pen->Width=0.5*ku+0.5;
  xxx->Canvas->Ellipse((x-d/2)*ku, (y-d/2)*ku, (x+d/2)*ku, (y+d/2)*ku);
}
dat.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#ifndef DAT_H
#define DAT_H
 
class Graf
{
private:    // User declarations
public:     // User declarations
    template <class Canv>
    void F1(Canv* xxx, double x, double y, double d, double ku);
    //template <typename T>
    //T F2(T a, T b);
};
 
#endif
Добавлено через 2 минуты
Вот цитата из книги по C++ (автор Валерий Лаптев):
"В системе Visual C++ 6 очень плохо реализованы шаблоны - много ошибок и плохо поддерживается стандарт. В
частности приведённые примеры работают не все. В системе Borland C++ Builder 6 всё работает правильно."

У меня среда программирования "Borland C++ Builder 6", но не работает.
0
 Аватар для Maluda
1280 / 598 / 116
Регистрация: 18.08.2009
Сообщений: 832
27.09.2016, 14:15
Лучший ответ Сообщение было отмечено Инженер_3 как решение

Решение

Инженер_3, еще раз повторяю, не нужен тебе здесь шаблон. Возьми ту функцию, что я тебе выше приводил и дальше используй так

C++
1
2
CustomDrawEllipse(Image1->Canvas, 50, 50, 20, 3.4);
CustomDrawEllipse(Printer()->Canvas, 50, 50, 20, 3.4);
Шаблоны используют, когда ты оперируешь типом, который может меняться. Здесь ты всегда работаешь с одним и тем же типом *TCanvas*
1
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
27.09.2016, 14:39
Цитата Сообщение от Инженер_3 Посмотреть сообщение
Боюсь спросить, а "тестовый проект" это что?
Сделай проект, в котором возникает твоя ошибка. Заархивируй этот проект и выложи сюда. Его скачают, запустят у себя и посмотрят как решить ошибку.

Добавлено через 21 минуту
А вообще Maluda Вам дело говорит.
1
3 / 3 / 0
Регистрация: 10.06.2016
Сообщений: 417
27.09.2016, 14:58  [ТС]
volvo, Большое спасибо, всё пошло после переноса из dat.cpp в Unit1.cpp, вот только Unit1.cpp, будет сильно раздут.
d7d1cd, тоже спасибо за участие в разрешении проблемы.
А вот и окончание:
C++
1
2
3
4
5
6
7
8
9
10
11
double x=50.0, y=50.0, d=60.0, ku=3.4;
  Graf *graf = new Graf;
 
  graf->F1(Image1, x, y, d, ku);
  TPrinter *Prn;//принтер
  Prn=Printer();
  Prn->BeginDoc();
  ku=23.62;
  graf->F1(Prn, x, y, d, ku);
  Prn->EndDoc();
  delete graf;
Правда, хотелось бы описание этой функции в отдельный файл, но может, моя среда программирования устарела.

Добавлено через 18 минут
Maluda, Большое спасибо, просто шедевр.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
27.09.2016, 14:58
Помогаю со студенческими работами здесь

Создание универсальной IDE С++ из emacs
Всем привет. Задался вопросом создания из редактора emacs универсальной среды разработки на языке C++ под себя. Сам ещё не пробовал его...

Создание универсальной библиотеки для включаемых файлов.
Включаю несколько файлов один в другой: &lt;!-- #INCLUDE File='svdbfunc.asp' --&gt; Получаются взаимные ссылки и естественно ругань типа...

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

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

Сократить код, в идеале оформив в виде универсальной функции
Есть кусок кода вида: for (int i = 0; i &lt; sizeOfFoundFlats; ++i) { if (foundFlats.type != type) { deleteFlat(i,...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
18
Ответ Создать тему
Новые блоги и статьи
сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
WordPad для Windows 11
Jel 10.01.2026
WordPad для Windows 11 — это приложение, которое восстанавливает классический текстовый редактор WordPad в операционной системе Windows 11. После того как Microsoft исключила WordPad из. . .
Classic Notepad for Windows 11
Jel 10.01.2026
Old Classic Notepad for Windows 11 Приложение для Windows 11, позволяющее пользователям вернуть классическую версию текстового редактора «Блокнот» из Windows 10. Программа предоставляет более. . .
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
Модель микоризы: классовый агентный подход 3
anaschu 06.01.2026
aa0a7f55b50dd51c5ec569d2d10c54f6/ O1rJuneU_ls https:/ / vkvideo. ru/ video-115721503_456239114
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR
ФедосеевПавел 06.01.2026
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR ВВЕДЕНИЕ Введу сокращения: аналоговый ПИД — ПИД регулятор с управляющим выходом в виде числа в диапазоне от 0% до. . .
Модель микоризы: классовый агентный подход 2
anaschu 06.01.2026
репозиторий https:/ / github. com/ shumilovas/ fungi ветка по-частям. коммит Create переделка под биомассу. txt вход sc, но sm считается внутри мицелия. кстати, обьем тоже должен там считаться. . . .
Расчёт токов в цепи постоянного тока
igorrr37 05.01.2026
/ * Дана цепь постоянного тока с сопротивлениями и источниками (напряжения, ЭДС и тока). Найти токи и напряжения во всех элементах. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа и. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru