Я пытаюсь создать структуру данных, которая имеет векторные функции для изучения C ++. В настоящее время я застрял, пытаясь скомпилировать код, подобный этому:
template<typename T>
class TestClass {
public:
T* data;
TestClass(const T& t) {
data = new T{ t };
}
~TestClass(void) {}
TestClass(const TestClass&) {}
T& operator[](int k) { return *data; }
const T& operator[](int k) const { return *data; }
class NestedClass {
public:
NestedClass(void) {}
~NestedClass(void) {}
T& operator*(void) { return operator[](0); }
};
NestedClass newNestedClass(void) {
return new NestedClass();
}
};
Я получаю неоднозначный вызов перегруженной функции на моем operator*
функция внутри моего вложенного класса. Хотя я думаю, что у меня возникла проблема (как компилятор узнает, если это его rhs / lhs), я не совсем уверен, как это исправить. Я хочу использовать operator[]
Функция для этого.
Я ожидаю, что эти две строки будут печатать одно и то же:
TestClass<int> t(1);
auto n = t.newNestedClass();
cout << t[0] << endl;
cout << *n << endl;
return 0;
Любой совет?
operator[]
что вы определили для вашего TestClass
никоим образом не «унаследован» или как-то «встроен» в ваш вложенный класс.
Вы можете думать о вложенных классах C ++ как об обычных классах, которые живут в «вложенном пространстве имен»: TestClass::NestedClass
в вашем примере кода.
Если вы хотите operator[]
для вашего вложенного класса, вы должны определить один с нуля (как вы сделали для вашего TestClass
).
РЕДАКТИРОВАТЬ 1: Возвращение классов (C ++ Is Не Джава)
Также обратите внимание, что C ++ не как например Java (с шаблоном выделения экземпляров классов с new
и полагаться на сборщик мусора для автоматического сбора «мусора»).
Итак, код такой:
NestedClass newNestedClass(void) { return new NestedClass(); }
не должен даже компилироваться.
Если вы вернули NestedClass
Экземпляр динамически распределяется с new
, вы должны вернуть указатель к этому, например:
// Note the "*" for the returned pointer
NestedClass* newNestedClass() {
return new NestedClass();
}
Но это скорее шаблон Java.
В C ++ вы можете просто захотеть вернуть экземпляр NestedClass без new
динамическое распределение; это должно работать просто отлично:
NestedClass newNestedClass() {
return NestedClass();
}
РЕДАКТИРОВАТЬ 2: Правильное управление ресурсами
Обратите внимание, что вы можете сделать T* data;
член private
для лучшей инкапсуляции и сокрытия информации. Вы предоставляете надлежащее общественности аксессоры (как operator[]
перегрузки) для доступа к данным вашего класса: выставить функции-члены аксессора, не члены данных.
Кроме того, вы динамично выделено data
в кучу, используя new
, Вы должны релиз динамически выделяемая куча памяти, чтобы избежать памяти (и ресурса) утечки.
Хорошее место для этого — ваш класс деструктор, например.:
class TestClass {
private:
T* data;
public:
...
~TestClass() {
// Release resoruces dynamically allocated
delete data;
}
}
Обратите внимание, что этот код:
data = new T{t};
просто динамически выделяет один экземпляр T
, инициализируя его значением t
,
Соответствующий код очистки:
delete data;
Однако, если вы хотите динамически выделить массив T
s, синтаксис:
data = new T[elementCount];
// ... initialize data to some value...
и соответствующий синтаксис очистки:
delete[] data; // Note the []!!
Также обратите внимание, что если вы хотите вручную управлять ресурсами в своем классе, вы должны рассмотреть также определение конструктор копирования а также копия задания operator=()
(см. так называемый Правило трех); и если вы хотите реализовать переместить семантику, Вы также должны рассмотреть возможность реализации переместить конструктор а также переместить назначение (в этом случае есть соответствующий «Правило 5»).
Но если вы полагаетесь на уже доступны RAII ресурсные менеджеры, лайк std::vector
Вы не должны тратить время, энергию и охоту на насекомых, управляя ресурсами вручную: это все автоматически управляемый std::vector
, или какой-либо класс контейнера вы выбираете (в этом случае у вас есть простой «Правило нуля» 🙂 То есть стандартный конструктор копирования, сгенерированный компилятором, оператор присваивания копии, конструктор перемещения, оператор присваивания перемещения и деструктор сделают трудную задачу.
Но, конечно, если это учебное упражнение, вы можете реализовать эти специальные функции-члены самостоятельно.