实施:Class 中的私有结构
Implementing: private structs in Class
我有一个列表 class,它使用两个对象:元素和迭代器
我考虑过制作 Element 和 Iterator classes,但最终决定使用结构。
V1。这有效...
template <class T>
struct Element
template <class T>
struct Iterator
template <typename T>
class List {
public:
typedef Iterator<T> iterator;
private:
};
如您所料,它允许 List 迭代器:
List<int> list;
List<int>::iterator iter = list.begin();
V2。另一种方法是在 class
中声明结构
template <typename T>
class List {
public:
template <class T>
struct Element
template <class T>
struct Iterator
private:
};
然而,在创建迭代器时必须包含第二个 <> 有点不太优雅,结构是 public:
List<int> list;
List<int>::Iterator<int> iter = list.begin();
V3。涉及将结构设为私有,这是更可取的:
template <class T>
class Iterator;
template <typename T>
class List {
public:
typedef Iterator<T> iterator;
private:
template <class T>
struct Element
template <class T>
struct Iterator
};
.
List<int> list;
List<int>::iterator iter list.begin();
Error 1 error C2079: 'begin' uses undefined class 'Iterator<T>' main.cpp 216
问题:
如何使结构私有,允许 public 访问迭代器并保持 List::iterator 语法?
eg List::iterator iter list.begin();
注意:
迭代器依赖于元素
代码:
#ifndef GUARD_List_h
#define GUARD_List_h
template <class T>
struct Element {
Element() : prev(nullptr), next(nullptr), data(), t_flag(" ") {}
Element<T>* prev;
Element<T>* next;
T data;
int elem_ID;
std::string t_flag;
};
template <class T>
struct Iterator {
Iterator(Element<T>* e = nullptr) : elem(e) {}
T& operator*(void) const {
if (elem->t_flag == "sentinel"){ std::cerr << "No Element to De-Reference - End of List Reached"; }
return elem->data;
}
T& operator++(void) { // ++prefix
elem = elem->next;
return elem->data;
}
T operator++(const int) { // postfix++
elem = elem->next;
return elem->prev->data;
}
T& operator--(const int) { // --prefix
elem = elem->prev;
return elem->data;
}
T operator--(void) { // postfix--
elem = elem->prev;
return elem->next->data;
}
Iterator<T>& operator+(const int val) {
for (int i = 0; i < val; i++){
elem = elem->next;
}
return *this;
}
Iterator<T>& operator-(const int val) {
for (int i = 0; i < val; i++){
elem = elem->prev;
}
return *this;
}
bool operator!=(const Iterator<T>& rhs) const {
return elem->elem_ID != rhs.elem->elem_ID;
}
bool operator==(const Iterator<T>& rhs) const {
return elem->elem_ID == rhs.elem->elem_ID;
}
bool operator>(const Iterator<T>& rhs) const {
return elem->elem_ID > rhs.elem->elem_ID;
}
bool operator<(const Iterator<T>& rhs) const {
return elem->elem_ID < rhs.elem->elem_ID;
}
bool operator>=(const Iterator<T>& rhs) const {
return elem->elem_ID >= rhs.elem->elem_ID;
}
bool operator<=(const Iterator<T>& rhs) const {
return elem->elem_ID <= rhs.elem->elem_ID;
}
Element<T>* elem;
};
template <typename T>
class List {
public:
List() : sentinel(new Element<T>), Element_count(0) {
sentinel->t_flag = "sentinel";
// double link: sentinel to itself
sentinel->next = sentinel;
sentinel->prev = sentinel;
}
virtual ~List() {
Element<T>* index = sentinel->next;
Element<T>* index_next = sentinel->next->next;
while (index->t_flag != "sentinel"){
delete index;
index = index_next;
index_next = index_next->next;
}
delete sentinel;
}
typedef Iterator<T> iterator;
Iterator<T> begin(void) const {
Iterator<T> it(sentinel->next);
return it;
}
Iterator<T> end(void) const {
Iterator<T> it(sentinel);
return it;
}
void push_back(const T val) {
Element<T>* elem = new Element<T>; // create Element<T> object
elem->data = val; // set Element<T> data
sentinel->prev->next = elem; // link: end of List to Element object
elem->prev = sentinel->prev; // link: Element object to end of List
elem->next = sentinel; // link: new end of List to sentinel
sentinel->prev = elem; // link: sentinel to new end of List
elem->elem_ID = Element_count++; // update: Element_count on grow
}
T at(const size_t pos) const {
return get_Element(pos)->data;
}
void del(const size_t pos) const {
Element<T>* elem = get_Element(pos); // get: Element for deletion
elem->prev->next = elem->next; // rejoin: double link
elem->next->prev = elem->prev; // rejoin: double link
delete elem;
Element_count--; // update: Element_count on shrink
}
void clear(void) {
Element<T>* index = sentinel->next;
Element<T>* index_next = sentinel->next->next;
while (index->t_flag != "sentinel"){
delete index;
index = index_next;
index_next = index_next->next;
}
// double link: sentinel to itself
sentinel->next = sentinel;
sentinel->prev = sentinel;
Element_count = 0;
}
size_t size(void) const {
return Element_count;
}
bool empty(void) const {
if (Element_count == 0){ return true; }
else { return false; }
}
private:
Element<T>* sentinel; // List sentinel
size_t Element_count; // List size
Element<T>* get_Element(const size_t pos) const {
if (empty()) {
std::cerr << "No Element - Empty List";
throw;
}
if (pos < 0 || pos >= Element_count){
std::cerr << "No Element - Out of Range";
throw;
}
Iterator<T> it;
if ((Element_count / 2) > pos) { // Determine efficent direction ?
it = begin()+1;
while ( it.elem->elem_ID != pos ){ it++; }
}
else {
it = end()-1;
while ( it.elem->elem_ID != pos ){ it--; }
}
return it.elem;
}
};
#endif
就 "elegance" 而言,冗余 typename
声明似乎是最大的问题:
如果你有一个嵌套的 class 或结构,你不需要将它模板化;它已经绑定到模板化 typename T
声明。
所以:
template <typename T>
class List {
public:
struct Element;
struct Iterator;
private:
};
允许你做:
List<int> x;
List<int>::iterator iter ( x.begin() );
由于 Iterator
是在 public 方法中返回的,因此无法标记为 private
。另一方面,Element
纯粹是一个实现细节,可以标记为私有。您需要确保它在任何使用它的方法之前被声明 或 只是向前声明。
template<typename T>
class List {
private:
struct Element; // or struct Element { <impl> };
public:
struct Iterator { < impl > };
private:
};
我有一个列表 class,它使用两个对象:元素和迭代器
我考虑过制作 Element 和 Iterator classes,但最终决定使用结构。
V1。这有效...
template <class T>
struct Element
template <class T>
struct Iterator
template <typename T>
class List {
public:
typedef Iterator<T> iterator;
private:
};
如您所料,它允许 List 迭代器:
List<int> list;
List<int>::iterator iter = list.begin();
V2。另一种方法是在 class
中声明结构template <typename T>
class List {
public:
template <class T>
struct Element
template <class T>
struct Iterator
private:
};
然而,在创建迭代器时必须包含第二个 <> 有点不太优雅,结构是 public:
List<int> list;
List<int>::Iterator<int> iter = list.begin();
V3。涉及将结构设为私有,这是更可取的:
template <class T>
class Iterator;
template <typename T>
class List {
public:
typedef Iterator<T> iterator;
private:
template <class T>
struct Element
template <class T>
struct Iterator
};
.
List<int> list;
List<int>::iterator iter list.begin();
Error 1 error C2079: 'begin' uses undefined class 'Iterator<T>' main.cpp 216
问题:
如何使结构私有,允许 public 访问迭代器并保持 List::iterator 语法?
eg List::iterator iter list.begin();
注意: 迭代器依赖于元素
代码:
#ifndef GUARD_List_h
#define GUARD_List_h
template <class T>
struct Element {
Element() : prev(nullptr), next(nullptr), data(), t_flag(" ") {}
Element<T>* prev;
Element<T>* next;
T data;
int elem_ID;
std::string t_flag;
};
template <class T>
struct Iterator {
Iterator(Element<T>* e = nullptr) : elem(e) {}
T& operator*(void) const {
if (elem->t_flag == "sentinel"){ std::cerr << "No Element to De-Reference - End of List Reached"; }
return elem->data;
}
T& operator++(void) { // ++prefix
elem = elem->next;
return elem->data;
}
T operator++(const int) { // postfix++
elem = elem->next;
return elem->prev->data;
}
T& operator--(const int) { // --prefix
elem = elem->prev;
return elem->data;
}
T operator--(void) { // postfix--
elem = elem->prev;
return elem->next->data;
}
Iterator<T>& operator+(const int val) {
for (int i = 0; i < val; i++){
elem = elem->next;
}
return *this;
}
Iterator<T>& operator-(const int val) {
for (int i = 0; i < val; i++){
elem = elem->prev;
}
return *this;
}
bool operator!=(const Iterator<T>& rhs) const {
return elem->elem_ID != rhs.elem->elem_ID;
}
bool operator==(const Iterator<T>& rhs) const {
return elem->elem_ID == rhs.elem->elem_ID;
}
bool operator>(const Iterator<T>& rhs) const {
return elem->elem_ID > rhs.elem->elem_ID;
}
bool operator<(const Iterator<T>& rhs) const {
return elem->elem_ID < rhs.elem->elem_ID;
}
bool operator>=(const Iterator<T>& rhs) const {
return elem->elem_ID >= rhs.elem->elem_ID;
}
bool operator<=(const Iterator<T>& rhs) const {
return elem->elem_ID <= rhs.elem->elem_ID;
}
Element<T>* elem;
};
template <typename T>
class List {
public:
List() : sentinel(new Element<T>), Element_count(0) {
sentinel->t_flag = "sentinel";
// double link: sentinel to itself
sentinel->next = sentinel;
sentinel->prev = sentinel;
}
virtual ~List() {
Element<T>* index = sentinel->next;
Element<T>* index_next = sentinel->next->next;
while (index->t_flag != "sentinel"){
delete index;
index = index_next;
index_next = index_next->next;
}
delete sentinel;
}
typedef Iterator<T> iterator;
Iterator<T> begin(void) const {
Iterator<T> it(sentinel->next);
return it;
}
Iterator<T> end(void) const {
Iterator<T> it(sentinel);
return it;
}
void push_back(const T val) {
Element<T>* elem = new Element<T>; // create Element<T> object
elem->data = val; // set Element<T> data
sentinel->prev->next = elem; // link: end of List to Element object
elem->prev = sentinel->prev; // link: Element object to end of List
elem->next = sentinel; // link: new end of List to sentinel
sentinel->prev = elem; // link: sentinel to new end of List
elem->elem_ID = Element_count++; // update: Element_count on grow
}
T at(const size_t pos) const {
return get_Element(pos)->data;
}
void del(const size_t pos) const {
Element<T>* elem = get_Element(pos); // get: Element for deletion
elem->prev->next = elem->next; // rejoin: double link
elem->next->prev = elem->prev; // rejoin: double link
delete elem;
Element_count--; // update: Element_count on shrink
}
void clear(void) {
Element<T>* index = sentinel->next;
Element<T>* index_next = sentinel->next->next;
while (index->t_flag != "sentinel"){
delete index;
index = index_next;
index_next = index_next->next;
}
// double link: sentinel to itself
sentinel->next = sentinel;
sentinel->prev = sentinel;
Element_count = 0;
}
size_t size(void) const {
return Element_count;
}
bool empty(void) const {
if (Element_count == 0){ return true; }
else { return false; }
}
private:
Element<T>* sentinel; // List sentinel
size_t Element_count; // List size
Element<T>* get_Element(const size_t pos) const {
if (empty()) {
std::cerr << "No Element - Empty List";
throw;
}
if (pos < 0 || pos >= Element_count){
std::cerr << "No Element - Out of Range";
throw;
}
Iterator<T> it;
if ((Element_count / 2) > pos) { // Determine efficent direction ?
it = begin()+1;
while ( it.elem->elem_ID != pos ){ it++; }
}
else {
it = end()-1;
while ( it.elem->elem_ID != pos ){ it--; }
}
return it.elem;
}
};
#endif
就 "elegance" 而言,冗余 typename
声明似乎是最大的问题:
如果你有一个嵌套的 class 或结构,你不需要将它模板化;它已经绑定到模板化 typename T
声明。
所以:
template <typename T>
class List {
public:
struct Element;
struct Iterator;
private:
};
允许你做:
List<int> x;
List<int>::iterator iter ( x.begin() );
由于 Iterator
是在 public 方法中返回的,因此无法标记为 private
。另一方面,Element
纯粹是一个实现细节,可以标记为私有。您需要确保它在任何使用它的方法之前被声明 或 只是向前声明。
template<typename T>
class List {
private:
struct Element; // or struct Element { <impl> };
public:
struct Iterator { < impl > };
private:
};