Форум программистов, компьютерный форум CyberForum.ru
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
dailydose
overmind
345 / 125 / 33
Регистрация: 21.07.2016
Сообщений: 603
#1

Перегрузка внутри класса - C++

19.08.2016, 07:57. Просмотров 426. Ответов 20
Метки нет (Все метки)

Есть класс Points, который использует обычные стандартные функции. Здесь для примера написал две функции(работают со значениями переменных по ссылке) increaseValue, increaseValue, чтобы проще было отобразить суть, на самом деле эти я пользуюсь другими функциями.
C++
1
2
3
4
5
6
7
8
9
10
template<typename T>
void increaseValue(T& value)
{
    value++;
}
template<typename T>
void decreaseValue(T& value)
{
    value--;
}
Для удобства работы с полями этого класса сделал перегрузку присваивания, чтобы не было такого:
C++
1
2
3
4
if (this->type == "Float")
    this->value.f = newValue;
else
    this->value.i = newValue;
Вместо этого можно использовать упрощенную запись:
C++
1
*this = newValue
и в завимости от того какого типа переменная newValue запишется значение в this->value.i или же в this->value.f
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Points
{
public:
    std::string type;
    union
    {
        int i;
        float f;
    } value;
 
    void readFloatValuesFromFile();
    void readIntegerValuesFromFile();
    void doSomething();
 
private:
    template<typename T>
    Points& operator=(T newValue);
};
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void Points::readFloatValuesFromFile()
{
    this->type = "Float";
    *this = 250.5;
}
void Points::readIntegerValuesFromFile()
{
    this->type = "Integer";
    *this = 100;
}
 
template<typename T>
Points& Points::operator=(T newValue)
{
    if (this->type == "Float")
        this->value.f = newValue;
    else
        this->value.i = newValue;
 
    return *this;
}
Теперь собственно вопрос можно ли сделать такую же перегрузку для этого кода?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
void Points::doSomething()
{
    if(this->type == "Float")
        increaseValue(this->value.f);
    else
        increaseValue(this->value.i);
 
    Sleep(500);
 
    if (this->type == "Float")
        decreaseValue(this->value.f);
    else
        decreaseValue(this->value.i);
}
вот в это
C++
1
2
3
4
5
6
7
8
void Points::doSomething()
{
    increaseValue(this);
 
    Sleep(500);
 
    decreaseValue(this);
}
Вряд ли в C++ есть подобная перегрузка. В голову пришла идея использовать геттер:
C++
1
2
3
4
5
6
7
8
void Points::doSomething()
{
    increaseValue(getValue());
 
    Sleep(500);
 
    decreaseValue(getValue());
}
Но тогда вопрос в том как определить этот метод?
C++
1
2
3
4
5
6
/* ??type?? */ Points::getValue()
{
    if (this->type == "Float")
        return this->value.f;
    return this->value.i;
}
Какой должен быть тип возвращаемого значения? Eсли этот метод возвращает float или int в зависимости от значения std::string type
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
19.08.2016, 07:57
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Перегрузка внутри класса (C++):

Перегрузка внутри класса - C++
Как описывается перегрузка внутри класса и вне его?

Перегрузка оператора >> для дочернего класса от базового виртуального класса - C++
Доброго вам времени суток! Программирую на С++ не давно, в связи с отсутствием должного времени на поиск ответа в глубинах учебников,...

Создать объект внутри класса, который может вызывать функцию этого класса - C++
Ребята помогите уже несколько дней мучаюсь. Хочу сделать программу в консоле демонстрации работы лифта в здании 2 этажа. Сделал класс...

delete внутри класса для самого класса - C++
Доброго времени суток, пишу программу для работы с матрицами. По условию дали лишь несколько библиотек, ни векторов ни cstdio. Для...

Заполнение вектора класса внутри самого класса - C++
class A { private: int a; public: A() { a = 0; }; A get(vector &lt;A&gt;* vec)

BST дерево. Инициализация класса внутри класса - C++
Здравствуйте, нужно реализовать класс дерева бинарного поиска с использованием итератора. Возник вопрос, как инициализировать через...

20
zss
Модератор
Эксперт С++
6403 / 5969 / 1945
Регистрация: 18.12.2011
Сообщений: 15,387
Завершенные тесты: 1
19.08.2016, 08:21 #2
А почему бы не сделать так
C++
1
2
3
4
5
6
7
template<typename T>
void Points::doSomething()
{
    increaseValue<T>(this);
     Sleep(500);
     decreaseValue<T>(this);
}
Но лучше increaseValue decreaseValue сделать членами класса и this не передавать.
1
dailydose
overmind
345 / 125 / 33
Регистрация: 21.07.2016
Сообщений: 603
19.08.2016, 10:54  [ТС] #3
Цитата Сообщение от zss Посмотреть сообщение
Но лучше increaseValue decreaseValue сделать членами класса и this не передавать.
Эти функции я привёл для примера. У меня же в коде на данный момент:
Цитата Сообщение от Случай#1
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
    if (health.type == "Float")
    {
        float temp;
        ReadProcessMemory(hProc, (LPVOID)ptr, &temp, entry.size, NULL);
        temp += health.value.f;
        WriteProcessMemory(hProc, (LPVOID)ptr, &temp, entry.size, NULL);
    }
    else
    {
        int temp;
        ReadProcessMemory(hProc, (LPVOID)ptr, &temp, entry.size, NULL);
        temp += health.value.i;
        WriteProcessMemory(hProc, (LPVOID)ptr, &temp, entry.size, NULL);
    }
Цитата Сообщение от Случай#2
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
void Trainer::printMessage()
{
std::cout << "\t\t* *   "
          << cfg->hotkey.health.name
          << " - increase "
          << getAmmount(cfg->health)
          << " Health         * *" << std::endl;
// print other data like a armour, money, etc...
}
 
inline std::string Trainer::getAmmount(Config::ammount& ammount)
{
    return (ammount.type == "Float") ? std::to_string(ammount.value.f) : std::to_string(ammount.value.i);
}
Во втором случае же для вывода чтобы преобразовать в строку написал вспомогательную функцию getAmmount, возвращающую строку. Думаю здесь можно и перегрузить, например так:
Цитата Сообщение от toString
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
std::ostream & operator<<(std::ostream & _stream, Points const & p)
{
    if (this->type == "Float")
        return _stream << p.f;
    else
        return _stream << p.i;
}
zss,
Цитата Сообщение от zss Посмотреть сообщение
А почему бы не сделать так
C++
1
2
3
4
5
6
7
template<typename T>
void Points::doSomething()
{
    increaseValue<T>(this);
     Sleep(500);
     decreaseValue<T>(this);
}
Компилятор ругается на health.doSomething() и armour.doSomething()
main.cpp(45): error C2672: "Points::doSomething": не найдена соответствующая перегруженная функция
main.cpp(45): error C2783: void Points::doSomething(void): не удается составить аргумент шаблон для "T"
main.cpp(31): note: см. объявление "Points::doSomething"


Вобщем, получилось много текста, а вопрос в целом звучит так: Как объявить функцию без аргументов, возвращающую разные типы данных?
C++
1
2
3
4
5
6
7
type_to_return Myfunction()
{
    if (blablah) 
         return 100; // int
 
    return 250.5; // float
}
0
Миниатюры
Перегрузка внутри класса  
zss
Модератор
Эксперт С++
6403 / 5969 / 1945
Регистрация: 18.12.2011
Сообщений: 15,387
Завершенные тесты: 1
19.08.2016, 12:02 #4
dailydose,
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
33
34
template<typename T>
void increaseValue(T& value)
{
    value++;
}
template<typename T>
void decreaseValue(T& value)
{
    value--;
}
 
template<typename T>
class Points
{
    T t;
public:
    Points():t(0){}
    void doSomething();
};
template<typename T>
void Points<T>::doSomething()
{
    increaseValue<T>(t);
    Sleep(500);
    decreaseValue<T>(t);
}
int main()
{
    Points<int> pi;
    pi.doSomething();
    Points<float> pf;
    pf.doSomething();
    return 0;
}
Мне кажется, это то, что Вам хотелось.
1
dailydose
overmind
345 / 125 / 33
Регистрация: 21.07.2016
Сообщений: 603
19.08.2016, 13:22  [ТС] #5
zss,
Цитата Сообщение от zss Посмотреть сообщение
C++
1
2
Points<int> pi;
* * Points<float> pf;
К сожалению, нет. Типы заранее неизвестны, они берутся из файла, поэтому и использую union{int i; float f;}value; совместно с std::string type;

C++
1
2
3
4
5
6
7
8
9
10
class Points
{
    std::string type;
    union
    {
        int i;
        float f;
    } value;
//...
}
Добавлено через 1 минуту

Не по теме:

You are missing the point.

You must have a specific type in use when you compile your program. The type of a thing is not changeable when you run your program.

All a template does is provide a cookie-cutter method for the compiler to generate functions at compile time.



Добавлено через 1 минуту

Не по теме:

оттуда же и этот код

Цитата Сообщение от Duoas
Кликните здесь для просмотра всего текста
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
union NumberUnion {
  int z;
  float x;
  double r;
};
 
enum NumberType { INT, FLOAT, DOUBLE };
 
struct Number {
  NumberUnion val;
  NumberType type;
};
 
 
Number string_to_number(string str) {
  Number num;
  if( /*str is best as an int*/ ) {
    num.type = INT;
    num.val.z = ...
  } else if( /*str is best as a float*/ ) {
    num.type = FLOAT;
    num.val.x = ...
  } else if( /*str is best as double*/ ) {
    num.type = DOUBLE;
    num.val.r = ...
  }
  return num;
}
 
int main() {
  string s = ...
  Number n = string_to_number(s);
 
  switch( n.type) {
   case INT:
    cout << "int " << n.val.z;
    break;
   case FLOAT:
    cout << "float " << n.val.x;
    break;
   case DOUBLE:
    cout << "double " << n.val.r;
    break;
  }
 
  cout << endl;
  return 0;
}

0
avgoor
915 / 550 / 119
Регистрация: 05.12.2015
Сообщений: 1,531
19.08.2016, 13:25 #6
dailydose, Вам нужно type erasure.
1
dailydose
overmind
345 / 125 / 33
Регистрация: 21.07.2016
Сообщений: 603
19.08.2016, 14:51  [ТС] #7
Цитата Сообщение от avgoor Посмотреть сообщение
type erasure.
В моём случае как это будет выглядеть?

Моя попытка
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#include <iostream>
#include <windows.h>
#include <string>
#include <fstream>
 
template<typename T>
struct point
{
    std::string type;
    T value;
};
 
class Trainer
{
public:
    void* health;
    void* armour;
 
    Trainer()
    {
        readFile();
    }
    ~Trainer()
    {
        delete health;
        delete armour;
    }
private:
    void readFile();
};
 
int main()
{
    Trainer trainer;
 
    // Error: Выражение должно иметь тип класса
    // trainer.health.value += 100;
    // std::cout << trainer.health.value << std::endl;
    
    // так работает, но опять же повторюсь - тип переменных заранее неизвестен
    point<int>* t =  (point<int>*)trainer.health; // клята магія
    t->value += 100;
    std::cout << t->value << std::endl;
    
    return 0;
 
}
 
void Trainer::readFile()
{
    std::string buff;
    std::ifstream ini("config.ini");
 
    // [copy it for armour]
    getline(ini, buff);
    if (buff == "Float")
    {
        health = new point<float>;
        (*(point<float>*)health).type = "Float"; // клята магія
 
        getline(ini, buff);
        (*(point<float>*)health).value = stof(buff); // клята магія
    }
    else
    {
        health = new point<int>;
        (*(point<int>*)health).type = "int"; // клята магія
 
        getline(ini, buff);
        (*(point<int>*)health).value = stoi(buff); // клята магія
    }
    // [/copy it for armour]
 
    /*
    ** paste it here:
    */
 
    ini.close();
}
Цитата Сообщение от config.ini
int
100
float
250.0
Такой вот простенький файл. Допустим первая строка тип health, вторая значение; третья строка тип armour, четвертая - значение
0
avgoor
915 / 550 / 119
Регистрация: 05.12.2015
Сообщений: 1,531
19.08.2016, 15:17 #8
dailydose, Вы невнимательно читали статью. Тип объекта отдельно хранить не надо. Надо определить шаблонный конструктор и шаблонный оператор приведения типа.
1
DrOffset
7315 / 4415 / 1000
Регистрация: 30.01.2014
Сообщений: 7,253
19.08.2016, 15:20 #9
Лучший ответ Сообщение было отмечено автором темы, экспертом или модератором как ответ
dailydose, можно что-то наподобие этого сделать:
Кликните здесь для просмотра всего текста
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
class MemoryGrabberBase
{
public:
    virtual void increaseMemory(HANDLE hProc, LPVOID ptr) = 0;
    virtual void decreaseMemory(HANDLE hProc, LPVOID ptr) = 0;
 
    virtual ~MemoryGrabberBase() {}
};
 
template <typename T>
class MemoryGrabber
    : public MemoryGrabberBase
{
public:
    explicit MemoryGrabber(T val)
        : m_value(val)
    {}
 
    void increaseMemory(HANDLE hProc, LPVOID ptr)
    {
        T temp;
        ReadProcessMemory(hProc, ptr, &temp, sizeof(T), NULL);
        temp += m_value;
        WriteProcessMemory(hProc, ptr, &temp, sizeof(T), NULL);
    }
    void decreaseMemory(HANDLE hProc, LPVOID ptr)
    {
        T temp;
        ReadProcessMemory(hProc, ptr, &temp, sizeof(T), NULL);
        temp -= m_value;
        WriteProcessMemory(hProc, ptr, &temp, sizeof(T), NULL);
    }
 
private:
    T m_value;
};
 
int main()
{
    //.......
 
    std::unique_ptr<MemoryGrabberBase> mgr;
 
    if(buff == "Float")
    {
        std::getline(ini, buff);
        mgr = std::make_unique<MemoryGrabber<float>>(std::stof(buff));
    }
    else if(buff == "Int")
    {
        std::getline(ini, buff);
        mgr = std::make_unique<MemoryGrabber<int>>(std::stoi(buff));
    }
 
    //.......
 
    mgr->increaseMemory(hProc, ptr);
    //.....
    mgr->decreaseMemory(hProc, ptr);
}

Естественно код неполный, его нужно адаптировать под твою задачу.
Но основная идея, думаю, ясна. Мы проверку строки делаем только один раз, при чтении конфига, а дальше работаем с полиморфным объектом единообразно.
1
dailydose
overmind
345 / 125 / 33
Регистрация: 21.07.2016
Сообщений: 603
19.08.2016, 15:23  [ТС] #10
DrOffset,
Скорее всего это именно то, что нужно. Сейчас буду разбираться
0
dailydose
overmind
345 / 125 / 33
Регистрация: 21.07.2016
Сообщений: 603
19.08.2016, 16:36  [ТС] #11
Цитата Сообщение от DrOffset Посмотреть сообщение
работаем с полиморфным объектом единообразно.
На самом деле же с памятью работает класс Game, который используется классом Trainer и оба эти класса пользуются данными, которые читает класс Config. http://pastebin.com/u/dailydose

Цитата Сообщение от DrOffset Посмотреть сообщение
Естественно код неполный, его нужно адаптировать под твою задачу.
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#include <iostream>
#include <windows.h>
#include <string>
#include <fstream>
#include <memory>
 
class pointBase
{
public:
    void* value;
    virtual ~pointBase() {}
    /*virtual void* getValue();*/
};
 
template<typename T>
class point : public pointBase
{
public:
    T value;
    point(T value)
    {
        this->value = value;
    }
    ~point() {}
    /*T getValue()
    {
        return value;
    }*/
};
 
class Trainer
{
public:
    std::unique_ptr<pointBase> health;
    std::unique_ptr<pointBase> armour;
 
    Trainer()
    {
        readFile();
    }
    ~Trainer(){}
private:
    void readFile();
};
 
int main()
{
    Trainer trainer;
 
    /*std::cout << trainer.health->getValue() << std::endl;*/
    std::cout << trainer.armour->value << std::endl;
 
 
    return 0;
 
}
 
void Trainer::readFile()
{
    std::string buff;
    std::ifstream ini("config.ini");
 
    // [copy it for armour]
    getline(ini, buff);
    if (buff == "Float")
    {
        getline(ini, buff);
        health = std::make_unique<point<float>>(std::stof(buff));
    }
    else
    {
        getline(ini, buff);
        health = std::make_unique<point<int>>(std::stoi(buff));
    }
    // [/copy it for armour]
 
    /*
    ** paste it here:
    */
    getline(ini, buff);
    if (buff == "Float")
    {
        getline(ini, buff);
        armour = std::make_unique<point<float>>(std::stof(buff));
    }
    else
    {
        getline(ini, buff);
        armour = std::make_unique<point<int>>(std::stoi(buff));
    }
 
    ini.close();
}
std::cout << trainer.armour->value << std::endl;

Значение не выводится, но при отладке отображается. Как всё-таки добраться до него?
http://www.cyberforum.ru/attachment....1&d=1471613449

config.ini всё тотже
Цитата Сообщение от config.ini
int
100
float
250.0
0
Миниатюры
Перегрузка внутри класса  
DrOffset
7315 / 4415 / 1000
Регистрация: 30.01.2014
Сообщений: 7,253
19.08.2016, 17:39 #12
Цитата Сообщение от dailydose Посмотреть сообщение
Как всё-таки добраться до него?
В этом и суть.
При этом подходе надо писать так, чтобы снаружи до него не надо было добираться.
Работай с интерфейсами - не нужен void*, и касты не нужны.
1
dailydose
overmind
345 / 125 / 33
Регистрация: 21.07.2016
Сообщений: 603
19.08.2016, 18:02  [ТС] #13
Цитата Сообщение от DrOffset Посмотреть сообщение
В этом и суть.
При этом подходе надо писать так, чтобы снаружи до него не надо было добираться.
а если тогда юзать геттер? как привёл в этом же коде, нужно только расскоментировать
C++
1
/*std::cout << trainer.health->getValue() << std::endl;*/
C++
1
2
3
4
    /*T getValue()
    {
        return value;
    }*/
но тогда компилятор ругается ...
getValue: не является членом "pointBase"
0
Миниатюры
Перегрузка внутри класса  
DrOffset
7315 / 4415 / 1000
Регистрация: 30.01.2014
Сообщений: 7,253
19.08.2016, 18:06 #14
dailydose, зачем тебе геттер? Сформулируй задачу.

Хочешь выводить на экран значения, сделай так:
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
33
34
35
class pointBase
{
public:
    virtual ~pointBase() {}
 
    virtual std::ostream & output(std::ostream & out) const = 0;
};
 
template<typename T>
class point
    : public pointBase
{
public:
    point(T value) : value(value)
    { }
    ~point()
    { }
 
    std::ostream & output(std::ostream & out) const
    {
        return out << value;
    }
 
private:
    T value;
};
 
int main()
{
    pointBase * base = new point<int>(42);
 
    base->output(std::cout);
 
   //......
}
1
dailydose
overmind
345 / 125 / 33
Регистрация: 21.07.2016
Сообщений: 603
19.08.2016, 18:08  [ТС] #15
Цитата Сообщение от DrOffset Посмотреть сообщение
Работай с интерфейсами - не нужен void*, и касты не нужны.
Интерфейс в плане "абстрактный класс", не содержащий реализации?

Мне же в конечном итоге нужно нечто
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
union
{
    int i;
    float f;
}health, armour;
 
std::string buff = readTypeFromCfg(); // returns "int"
if(buff == "Float")
    health.f = readValueFromCfg();
else
    health.i = readValueFromCfg(); // returns 100
 
buff = readTypeFromCfg(); // returns "Float"
if(buff == "Float")
    armour.f = readValueFromCfg(); // returns 250.0
else
    armour.i = readValueFromCfg();
и чтобы дальше можно было делать так:
C++
1
2
health += 100;
armour += 150.0;
0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
19.08.2016, 18:08
Привет! Вот еще темы с ответами:

Объявление дружественного класса внутри класса - C++
class A{ friend class B{ B(A &amp;a); } } Подскажите пожалуйста, такое возможно или нет, я хотел чтобы...

Видимость экземпляра класса внутри класса - C++
Здравствуйте! Пытаюсь вывести openCV видео в QT виджете. На данный момент в слоте обновления картинки инициализирую класс cv::VideoCapture...

Методы класса внутри определения класса - C++
Все привет! Решил закрепить свои знания по C++, читаю Р.Лафоре - &quot;Объектро-ориентированное программирование в C++&quot;. В книге, на...

Инициализация класса A внутри класса B - C++
заранее извиняюсь, наверняка подобное было на одной из 1000 страниц=)... есть 2 класса //собственно первый класс class matrix ...


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

Или воспользуйтесь поиском по форуму:
15
Yandex
Объявления
19.08.2016, 18:08
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru