1.typename与class的区别
关键字typename被用来作为型别之前的标识符号。
模板分为类模板与函数模板,特化分为全特化与偏特化。全特化就是限定死模板实现的具体类型,偏特化就是如果这个模板有多个类型,那么只限定其中的一部分。
template <class T>
class MyClass{
typename T::SubType * ptr;
...
};
class Q{
typedef int SubType;
...
};
class Q{
class SubType;
...
};
在这里,typename指出SubType是class T中定义的一个类别,因此ptr是一个指向T::SubType型别的指针。如果没有关键字typename,SubType会被当成一个static成员,*会被解释为乘法。
注意,如果要把一个template中的某个标识符号指定为一种型别,就算是意图显而易见,关键字typename也是不能省略的,因此C++的一般规则是,除了使用typename修饰之外,template内的任何标识符号都被视为一个值而不是一个型别。
2.空类调用默认产生的函数
class test
{
public:
test(); // 缺省构造函数
test( const test& ); // 拷贝构造函数 //这里必须使用& 防止一直递归调用拷贝构造,造成栈溢出
~test(); // 析构函数
test& operator=( const test& ); // 赋值运算符
test* operator&(); // 取址运算符
const test* operator&() const; // 取址运算符 const
};
test *t = new test(); //缺省构造函数
delete t; //析构函数
test t; //缺省构造函数
test t1(t2); //拷贝构造函数
t1 = t2; //赋值运算符
test *p = &t; //取址运算符(非const)
const test *p = &t; //取址运算符(const)
3.虚函数
一般修饰类的成员函数 不包括以下几种。
(1)不能修饰普通函数;静态成员函数;内联成员函数;构造函数;友元函数。
4.重写,重载和重定义
重载:
- 函数名称必须相同。
- 参数列表必须不同(个数不同、类型不同、参数排列顺序不同等)。
- 函数的返回类型可以相同也可以不相同。
- 仅仅返回类型不同不足以成为函数的重载。
重定义:也叫做隐藏,子类重新定义父类中有相同名称的非虚函数 ( 参数列表可以不同 ) ,指派生类的函数屏蔽了与其同名的基类函数。发生在继承中。
重写:也叫做覆盖,一般发生在子类和父类继承关系之间。子类重新定义父类中有相同名称和参数的虚函数。
如果一个类,存在和父类相同的函数,那么,这个类将会覆盖其父类的方法,除非你在调用的时候,强制转换为父类类型,否则试图对子类和父类做类似重载的调用是不能成功的。
重写需要注意:
1、 被重写的函数不能是static的。必须是virtual的
2 、重写函数必须有相同的类型,名称和参数列表
3 、重写函数的访问修饰符可以不同。尽管virtual是private的,派生类中重写改写为public,protected也是可以的
重定义规则如下:
a 、如果派生类的函数和基类的函数同名,但是参数不同,此时,不管有无virtual,基类的函数被隐藏。
b 、如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有vitual关键字,此时,基类的函数被隐藏(如果相同有Virtual就是重写覆盖了)。
5.子类与父类
1、public:public表明该数据成员、成员函数是对所有用户开放的,所有用户都可以直接进行调用
2、private:private表示私有,私有的意思就是除了class自己之外,任何人都不可以直接使用,私有财产神圣不可侵犯嘛,即便是子女,朋友,都不可以使用。
3、protected:protected对于子女、朋友来说,就是public的,可以自由使用,没有任何限制,而对于其他的外部class,protected就变成private
创建子类对象:
1.构造函数需要是public
2.构造析构的调用顺序
(1)父类的构造函数
(2)子类的构造函数
(3)子类的析构函数
(4)父类的析构函数