Мне нужно создать конструктор с двумя целыми числами в качестве аргументов.
Оттуда мне нужно вызвать метод, взяв эти целые числа по ссылке. Внутри этого метода я должен динамически преобразовывать целые числа в char*
тип (массив цифр).
В конце конструктора у меня должно быть два char*
массивы вместо начальных целых чисел.
Я вроде как должен сделать это так, потому что другой класс делает то же самое, но на структурах. И сохраните их в атрибутах шаблона.
Я новичок в языке C ++, но мое первое предположение было использовать шаблоны. Я провел небольшое исследование по этой теме и выяснил, что это должно сработать.
Я бы хотел скомпилировать все это сам, но путаница с реализацией классов c ++ в моей голове приводит к довольно длинному списку ошибок компиляции.
Первый вопрос — это можно сделать с помощью шаблонов?
Второй вопрос, потому что я уже что-то написал сам:
template <class type> class Addition {
type num_a;
type num_b;
void convert(type, type);
public:
Addition(type, type);
}
template <class type> Addition::Addition(type a, type b) {
convert(&a, &b);
num_a = a;
num_b = b;
}
template <class type> Addition::convert(type *a, type *b) {
int temp_a = a, temp_b = b;
a = char[256], b = char[256];
// converting
}
Это хорошо, или я сделал что-то не так?
Есть ли у вас какие-либо предложения о том, как я реализую классы в C ++?
Почему я не могу инициализировать атрибут значением, например:
template <class type> class Addition {
type outcome = 0;
}
И если нет необходимости использовать это ключевое слово в C ++, как мне сделать что-то подобное ?:
template <class type> Addition::Foo(type a, type b) {
this->a = a; // a = a;
this->b = b; // b = b;
}
отказЯ не могу судить, действительно ли вам нужны шаблоны для того, что вы делаете. Это будет зависеть от количества различных типов, с которыми вы хотите, чтобы ваш шаблон класса Adddition работал с. Если вы будете использовать его только для int
, то, возможно, это внесет ненужную сложность. Вы всегда можете выполнить рефакторинг позже (это будет подход Agile).
Сказав, что, если вы хотите использовать шаблоны, обычное соглашение состоит в том, чтобы написать T
для параметра шаблона, и использовать type
для вложенного typedef
внутри шаблона класса. С помощью typename
или же class
это дело вкуса, но typename
подчеркивает тот факт, что встроенные типы также могут быть переданы в качестве аргументов. Обратите внимание, однако, что с параметры шаблона вам нужно будет написать
template<template<typename> class U> SomeClass { /* your definition */ };
^^^^^ // <-- NOT typename here
что подчеркивает тот факт, что только шаблоны классов могут быть переданы в качестве аргументов.
Есть несколько других провалов, которые можно упомянуть о вашем коде, которые могут привести к его некомпиляции (отсутствует возвращаемый тип в convert()
и отсутствует точка с запятой в определении класса):
template <typename T>
class Addition
{
static const std::size_t N = 256; // are you sure that 256 is all you'll ever need?
T num_a;
T num_b;
void convert(T const*, T const*); // by T const*, not T*
public:
Addition(T const&, T const&); // by T const&, not T
}; // <-- make sure to end class definitions with a semi-colon!
template <typename T>
Addition::Addition(T const& a, T const& b)
{
convert(&a, &b);
num_a = a;
num_b = b;
}
template <typename T>
void Addition::convert(T const* a, T const* b) // <-- use T const* if you don't modify the parameters
^^^^ // <-- you forgot the return type
{
int temp_a = a, temp_b = b;
a = char[N], b = char[N]; <-- hardcoded 256 is bad practice, better to keep that in 1 place only
// converting
}
В C ++ 11 вы даже можете использовать делегирующие конструкторы (поддерживается последней версией Visual C ++ и, конечно, gcc / Clang) и пишите
template <typename T>
Addition::Addition(T const& a, T const& b)
:
Addition(&a, &b) // delegate to the other constructor
{}
template <typename T>
Addition::Addition(T const* a, T const* b) // <-- use T const* if you don't modify the parameters
{
int temp_a = a, temp_b = b;
a = char[N], b = char[N]; <-- hardcoded 256 is bad practice, better to keep that in 1 place only
// converting
}
Наконец, поскольку определение шаблона в любом случае должно быть в заголовках, вы можете даже написать все внутри определения класса следующим образом:
template <typename T>
class Addition
{
static const std::size_t N = 256; // are you sure that 256 is all you'll ever need?
T num_a;
T num_b;
Addition(T const*, T const*) // by T const*, not T*
{
int temp_a = a, temp_b = b;
a = char[N], b = char[N];
// converting
}
public:
Addition(T const&, T const&) // by T const&, not T
:
Addition(&a, &b) // delegate to the other constructor
{}
}; // <-- make sure to end class definitions with a semi-colon!
Это избавляет вас от утомительного написания как объявлений, так и определений всех функций-членов. Для коротких и полезных классов (к которым вы все равно должны стремиться) это предпочтительный способ написания шаблонов, но для очень длинных определений вы можете разделить объявление и определение.
Наконец, как объяснил @tacp, вам действительно нужно использовать this->a
устранить неоднозначность члена данных класса из параметра функции. По этой причине люди часто пишут данные членов с последующим подчеркиванием или m_
префикс.
Для ваших последних вопросов:
template <class type> class Addition {
//type outcome = 0;
//^^^^you have to call default constructor of type
type outcome = type();
}
Лучше использовать typename
для соглашения, используя class
тоже нормально.
template <class type> Addition::Foo(type a, type b) {
this->a = a; // a = a;
this->b = b; // b = b;
}
Если переданный параметр и член имеют одно и то же имя, вам необходимо использовать this
, Вы не можете сделать
a =a;
b =b;
поскольку a,b
находятся в местном масштабе, но this->a
означает член класса a
,
Поскольку вы всегда хотите конвертировать целые числа в массив символов, я не думаю, что вам действительно нужны шаблоны. Если вы не хотите конвертировать double, float и другие типы в char*
также в будущем. Я не посмотрел все вопросы, поэтому могут быть и другие.