#c #vector #c -standard-library
#c #вектор #c -standard-library
Вопрос:
Я пытаюсь написать свой собственный векторный класс на C .В частности, я хочу реализовать норму как функцию-член. Следующий классический фрагмент кода — это то, что я сделал:
#include <iostream>
#include <cmath>
template <typename T>
class vector{
private:
T* elem;
std::size_t _size;
public:
vector(const std::size_t size) : elem{new T[size]}, _size{size} {}
~vector(){ delete[] elem;}
std::size_t size() const { return _size;}
Tamp; operator[](std::size_t i){ return elem[i];}
const Tamp; operator[](std::size_t i) const{ return elem[i];}
friend T norm();
};
template <typename T>
T vector::norm(){
T sum{0};
for (auto i=0u;i<_size; i){
sum =elem[i];
}
return std::sqrt(sum);
}
int main(){
vector<double> v{10};
for (auto i=0u;i<v.size(); i){
v[i] = i;
}
std::cout << v.norm() <<std::endl;
return 0;
}
Очевидно, что я мог бы определить функцию norm
внутри класса, но я хотел определить ее снаружи, потому что в принципе тело одной из функций-членов может быть длиной в несколько строк.
Как только я пытаюсь скомпилировать, компилятор сообщает, что:
- ‘template<class T> class vector’ используется без аргументов шаблона
_size
,elem
не объявленный в области видимости- ‘class vector<double>’ не имеет члена с именем ‘norm’
но я не могу понять, что не так, и как это исправить! В частности, я не понимаю последнего пункта: я явно объявлен norm()
как функция-член! Как я должен изменить свой код?
Ответ №1:
Вы объявляете norm()
как friend
функцию, поэтому на самом деле она не является членом самого vector
класса. Вы сообщаете компилятору, что некоторая внешняя функция, не являющаяся членом T norm()
, является другом vector
, чтобы она могла получить доступ vector
к закрытым членам. Но тогда вы на самом деле не определяете такую T norm()
функцию!
Правильный способ реализации norm()
в качестве члена с определением вне объявления класса будет выглядеть следующим образом:
template <typename T>
class vector{
...
public:
...
T norm(); // <-- remove 'friend'!
};
template <typename T>
T vector<T>::norm(){ // <-- note the extra <T>!
T sum{0};
for (auto i = 0u; i < _size; i){
sum = elem[i];
}
return std::sqrt(sum);
}
На заметку:
Вы могли бы рассмотреть возможность использования SFINAE, чтобы опустить объявление определение типов norm()
for T
, которые std::sqrt()
не поддерживаются (нецелые числа / типы с плавающей запятой, такие как строки и т. Д.).
Кроме того, ваш vector
класс не реализует правило 3/5/0 для правильного управления своим внутренним массивом. Вам нужно добавить к нему соответствующие конструкторы копирования / перемещения и операторы присваивания копирования / перемещения.
Комментарии:
1. Понятно, спасибо! Таким образом, я все еще могу получить доступ к данным-членам, т. Е.
elem
И_size
, Когда я нахожусь вне класса, верно?2. Я только начал введение в классы, и это первая часть. Я пытался добавить норму самостоятельно, но я застрял, как вы видели 🙂
3. @Vefhug » Я все еще могу получить доступ к данным-членам… когда я нахожусь вне класса, верно? » — если вы правильно объявите
norm()
как член и закодируете его определение с правильным синтаксисом, чтобы компилятор знал, на какой экземплярvector
смотреть, тогда да, ваше внешнее определениеnorm()
может получить доступ к данным членаvector
. » Я только начал введение в классы » — какое введение вы используете, которое сразу переходит к использованию шаблонов и разделению объявлений из определений элементов шаблона? Это довольно сложные темы для ознакомления с классами.