cpp好难啊啊啊
重载流插入运算符和流提取运算符
重载流插入运算符写法:
// 重载为友元函数
ostream &operator<<(ostream & os, Object & obj){
// dosomething...
return os;
}
重载流提取运算符写法:
// 重载为友元函数
istream &operator>>(istream & is, Object & obj){
// dosomething...
return is;
}
流插入和流提取运算符也可以重载为友元函数,一般不会重载为成员函数,因为写法上会变成这样:
class Object{
public:
ostream & operator<<(ostream & os); // 成员函数
friend istream & operator>>(istream & is, Object & obj); // 友元函数
};
// 调用方式
auto obj = new Object();
obj<< cout;
cin>> obj;
重载强制类型转换运算符
在C++中,类名其实也算个运算符,即强制类型转换运算符。
重载强制类型转换运算符时,不需要指定返回值类型。
重载double类型转换:
class Object{
private:
int a = 10;
double da = 10.1;
public:
operator double(){
return this->da;
}
};
auto obj = new Object();
cout << (double) *obj << endl; // 10.1
重载自增自减运算符
重载前置的表达式时,调用参数个数正常的重载函数。
重载后置的表达式时,调用多出一个参数的重载函数。
前置形式自增自减运算符的返回值类型是Object &
后置自增自减运算符返回值类型是Object
class Object{
private:
int n;
public:
Object & operator++(){
// ++前置
n++;
return *this;
}
Object operator++(int k){
// 后置++
Object t_obj(*this);
n++;
return t_obj; // 返回修改前的对象
}
// -- 略
};
类的继承与派生
继承的概念
通过已有的类建立新类的过程,叫做类的派生。原来的类称为基类,也称为父类或一般类;新类称为派生类,也称为子类或特殊类。派生类派生自基类,或继承于基类,也可以说基类派生了派生类。派生机制是C++语言及面向对象程序设计方法的重要特征之一。
若派生类中定义了一个与基类中同名的成员,这种情况下,若派生类的成员函数访问这个同名成员,或通过派生对象访问这个同名成员时,除非特别指明,访问的就是派生类中的成员,这种情况叫“覆盖”,即派生类的成员覆盖基类同名成员。覆盖也称为重定义或重写。
派生类的定义与大小
派生类的写法:
class child : (public|private|protected) parent{
// ...
}
派生类的大小 = 基类的大小 + 派生类的大小(有可能会边界对齐)
继承关系的类之间的访问
如果基类的静态成员是公有的或者是保护的,则他们被其派生类继承为派生类的静态成员。访问这些成员是,通常用“类名::成员名”的方式引用或调用。无论有多少个对象被创建,这些成员都只有一个拷贝,他为基类和派生类的所有对象所共享。
派生类中的成员函数可以访问基类中的公有成员变量,但不能直接访问基类中的私有成员变量。
在基类和派生类有同名函数的情况下,如果通过派生类的对象向调用基类中的函数,可以通过派生对象名.基类名::函数名的方式调用,如:
child.Parent::show();
protected修饰符
在基类中,一般都将需要隐藏的成员说明未保护成员而非私有成员。将基类中成员变量的访问方式修改为protected后,在派生类中可以直接访问。
多重继承
C++允许从多个类派生一个类,即一个派生类可以有多个基类。
多重继承是,如果多个基类中有同名的成员,则他们都被继承到派生类中。这时候会出现二义性问题。
解决办法是,当要访问派生对象中的某个成员变量时,添加“基类::"作为前缀,指明需要访问从哪个基类来的,从而可以排除二义性。
类型兼容规则
- 派生类的对象可以赋值给基类对象
- 派生类对象可以用来初始化基类引用
- 派生类对象的地址可以复制给基类指针,即派生类的指针可以赋给基类的指针
私有继承
继承方式说明符可以省略,默认私有继承
基类中的公有成员和保护成员,都成为派生类的私有成员
保护继承
基类中的公有成员和保护成员成为派生类的保护成员
派生类的构造函数和析构函数
调用派生类构造函数执行顺序:按类继承方式说明符顺序执行基类构造函数,如果派生类构造函数的初始化列表有基类构造函数,则执行该构造函数,否则执行默认的无参构造函数
基类构造函数->派生类成员变量的构造函数->派生类构造函数
派生对象消亡时析构函数的执行顺序:先执行本类(派生类)的析构函数,再执行基类的析构函数。
创建派生类的对象时,需要执行基类的构造函数,如果已经有了带参的构造函数,那么必须要有一个无参的构造函数。
类之间的关系
继承关系也称为“is a"关系或”是“关系,表现为派生类。
组合关系也称为“has a"关系或”有“关系,表现为封闭类。
互包含关系的类
如果确实需要循环定义两个类,可以让其中的一个类使用指针。
基类与派生类指针的互相转换
当派生类指针指向基类对象时,必须要将基类指针强制转换成派生类指针。