Essential C++ 笔记 - 第四章基于对象的编程风格
C++类的知识点
一、实现Triangular Class及对应的Triangular_Iterator Class
class Triangular_iterator {
public:
Triangular_iterator(int index) : _index(index - 1) {}
bool operator==(const Triangular_iterator& ) const;
bool operator!=(const Triangular_iterator& ) const;
int operator*() const;
Triangular_iterator& operator++(); // 前置版
Triangular_iterator& operator++(int); // 后置版
private:
void check_integrity() const;
int _index;
};
inline bool Triangular_iterator::operator==(const Triangular_iterator& rhs) const {
return _index == rhs._index;
}
inline bool Triangular_iterator::operator!=(const Triangular_iterator& rhs) const {
return _index != rhs._index;
}
inline bool Triangular_iterator::operator*() const {
check_integrity();
return Triangular::_elems[_index];
}
// 前置++:先加一,然后放入寄存器
// 后置++:先放入寄存器,后加一
inline Triangular_iterator& Triangular_iterator::operator++() {
++_index;
check_integrity();
return *this;
}
inline Triangular_iterator& Triangular_iterator::operator++(int) {
Triangular_iterator tmp = *this;
++_index;
check_integrity();
return tmp;
}
inline void Triangular_iterator::check_integrity() const {
if (_index >= Triangular::_max_elems) {
throw exception("iterator overflow");
}
if (_index >= Triangular::_elems.size() ) {
Triangular::gen_elements(_index + 1);
}
}
class Triangular {
public:
// 一组重载的constructors
Triangular(); // default constructor
Triangular(const Triangular& rhs); // copy constructor
Triangular(int len, int begin_pos, int next);
Triangular& operator=(const Triangular& rhs);
void gen_elements(int length);
// destructor
~Triangular();
typedef Triangular_iterator iterator;
Triangular_iterator begin() const {
return Triangular_iterator(_begin_pos);
}
Triangular_iterator end() const {
return Triangular_iterator(_begin_pos+_length);
}
friend int Triangular_iterator::operator*();
friend void Triangular_iterator::check_integrity();
private:
int _length;
int _begin_pos;
int _next;
static vector<int> _elems;
};
// Memberwise Initialization
Triangular::Triangular() {
_length = 1;
_begin_pos = 1;
_next = 0;
}
// Member Initialization
Triangular::Triangular(int len, int begin_pos, int next) : _length(len), _begin_pos(begin_pos), _next(next) {
}
// copy constructor
Triangular::Triangular(const Triangular& rhs) : _length(rhs._length), _begin_pos(rhs._begin_pos), _next(rhs._next){
}
// copy assignment operator
Triangular& Triangular::opertor=(const Triangular& rhs) {
_length = rhs._length;
_begin_pos = rhs._begin_pos;
_next = rhs._next;
return *this;
}
void Triangular::gen_elements(int length) {
if (length < 0 || length > _max_elems) {
// 发送错误信息,然后return
}
if (_elems.size() < length) {
int ix = _elems.size() ? _elems.size()+1 : 1;
for (; ix <= length; ++ix) {
_elems.push_back(ix*(ix+1)/2);
}
}
}
c++构造函数不能是虚函数:
vptr指针指向虚函数表,执行虚函数的时候,会调用vptr指针指向的虚函数的地址。
当定义一个对象的时候,首先会分配对象内存空间,然后调用构造函数来初始化对象。vptr变量是在构造函数中进行初始化的。又因为执行虚函数需要通过vptr指针来调用。如果可以定义构造函数为虚函数,那么就会陷入先有鸡还是先有蛋的循环讨论中。
基类的析构函数必须是虚函数:
BaseClass *base = new BaseClass(); 当我们执行 delete base时,会调用析构函数为我们释放资源。
BaseClass *sub = new SubClass(); 如果BaseClass基类的析构函数不是虚函数的时候,当我们执行delete sub时,只会释放BaseClass 基类申请的资源,而不是释放SubClass派生类的资源。
成员列表初始化:
Member Initialization
二、将iostream运算符重载
ostream& operator<<(ostream& os, const Triangular& rhs) {
os << "( " << rhs._begin_pos() << ", " << rhs.length() << " )";
return os;
}
istream& operator>>(istream& is, Triangular& rhs) {
int bp, len;
is >> bp >> len;
rhs._begin_pos(bp);
rhs._length(len);
return is;
}