--
分类: C/C++
2014-01-09 22:22:48
Class ClassName
{
Private:
Int a,b,c;
Public:
Void set(int a,int b,int c);
Void fun();
};
若成员函数很短,可以直接在内部定义,单位了清晰,还是外面定义。
若很短,外部定义为内联函数效果一样。
Inline void ClassName::set(....)
{..................}
如果只对对象读操作,通常定义为const成员函数,可以让别人清晰看到不会改变对象值。而且,能够作为const的尽量写为const。Void print() const;
重载:函数名称相同,但是参数类型与个数、返回值不同
操作符重载:
Class **
{
Point operator+(const Point& a, const Point& b);
}
Point Point::operator+(const Point& a, const Point& b)
{
Point s;
S.set(a.x + b.x, a.y + b.y);
Return s;
}
调用:operator+(a,b) Point
:: 、 。 。* ?: sizeof typedef都不可以重载。
**.h
#ifndef HEAD_H
#define HEAD_H
Class A
{
........
};
#endif
**.cpp
#include “**.h”
#include
Using namespace std;
成员函数定义
静态成员:全局数据区,所有对象共有。作为共有很危险
静态成员函数:静态成员私有,静态成员函数可以不捆绑对象的调用访问静态成员,且只能访问静态成员,不能访问类的其他成员。但是可以通过传递对象指针访问对象变量。
静态成员变量className::num = 0;
Frind函数,类定义中直接声明为friend,相应其他类可以直接调用
该函数声明:friend 类名 函数名()
构造函数:
和类同名,无返回值。同样可以通过set()实现,但是多了步骤
初始化简单做法:construct(string name = “noName”){ Name = name; }
成员列表:Student(string n = “noName”, int ssID=0):id(ssID),name(n){......}
一次性对象:无名对象,多在参数传递时用到。
局部对象初始化:根据运行对象的顺序决定对象创建的顺序,静态对象只创建一次。
全局对象初始化:main之前就已经初始化成功,出错很难定位,方法可以先局部后全局,或是打印出来。
全局对象,在**.h中定义Student stu(18); 在另外一个文件中应用
Extern Student stu,Tutor tur(stu).,会出现因为编译器原因导致对象创建顺序不一样,所以避免设置全局对象。,这是程序设计重用及安全的要诀。更不要让全局对象之间相互依赖。
类中组合多个类对象,不是按照构造顺序,而是按照定义顺序。
析构顺序正好与构造顺序相反。
拷贝构造函数:Person A(“aa”); Person B = A; 深拷贝,均构造析构
Person B(A); 浅拷贝,仅仅只是个指针,构造一次。可以使用自定义拷贝构造函数。尽量使用引用传递,且尽量使用常量引用传递。
浅拷贝:对象本体与对象实体一致。
深拷贝:对象本体与对象实体不一致。
深拷贝需要动态内存分配。本体释放时需要释放内存。析构函数来完成。
深拷贝需要重载运算符:P2 = P1// Person P1(“dsadf”);.
Person &operator=(Person& s)
{
If(this == &s) return s;
Delete [] name;
Name = new char[strlen(s.name)+1];
If (Name)
{
Strncpy(Name, s.name,strlen(s.name));
Retunr *this;
}
}
一旦重构运算符、深拷贝,说明申请了内存,则需要析构函数,将申请内存释放掉。
继承:
Class B: public BaseClass
{
....// 派生类对象总是含有基类对象。具体空间安排的前后顺序不定。
}
保护成员与私有成员,不能被我们公共访问,可被类内部的成员函数访问。
子类可以访问父类的protected成员、函数,但是其他类就不行。
派生类默认无参构造函数,首先调用父类构造函数,若父类定义含参构造函数则会出现问题。
修改数据的权限:一般该成员在父类中也是可见的,private派生类 public : using Base:: data;
继承与组合:物理结构上都是包含关系,但是性质上完全不同。
组合:类中含有对象成员的情形。
采用继承还是组合,首先从两个类对象的性质分,性质相同则一个类拥有另一个类大部分操作;若都太抽象分不清,如果操作多共同则用继承会好些。组合则职责分明,麻烦点但是调试直接明了。
多重继承:
Class A {。。。}; class B{...};
Class C:public A, public B {...};
若C继承了A、B相同的成员、方法,如何区分出来到底是谁的成员、方法,导致基类成员的名称冲突。通过C.A::**;或是C.B:**。
多重继承几个子类继承自相同子类,会出现含义不清晰的现象。
所以希望可以有根本的基类只有一个副本,则子类共享该基类的所有成员与方法。(菱形继承关系),用到就是虚拟继承。
Class Base {...}; class A:virtual public Base {........}; Class B:virtual public Base {.......};
Class C:public A,public B {...构造需要调用A() B()构造...};
多重继承,调试、模糊性问题尽量少用多重继承。一些多重继承功能强大的库多用来组合使用,用户很少继承。
多态
Void fun(student &x)//根据是对象类型判断:本科生还是研究生,执行相应扣费操作。多个状态。
若只支持继承但不支持多态,则不能称作支持面向对象编程。
C++通过虚函数实现多态。
Class Base { virtual void display(); }; class A : public Base { virtual void dispaly() ; };
Void fun (Base &x) {..x.dispaly();.}
一旦声明为虚函数,以后继承的同名函数均为虚函数。
包含虚函数的对象存在一个虚函数指针指向虚函数列表,编译器滞后处理,运行时根绝数据类型执行相应的虚函数。
虚函数必须是父子类之间所有参数、返回值均要完全一致,而不是重载。但是返回是父子类型的对象则另当别论,出现多态操作。
静态成员函数不能为虚函数,不受对象捆绑,也就失去多态意义。内联函数不能为虚函数(内联函数不能再运行中动态确定位置,虚函数在类中定义也视为非内联)。
构造函数不能为虚函数,析构函数可以并通常是虚函数。析构有些指向基类,有些事子类,针对不同对象类型执行不同操作。
减少冗余代码:按层次建立类关系,拥有共同的很小基类,将需要根据子类类型不同执行不同操作的接口定义为虚函数。
类型转换:
Dynamic_cast:专门针对有虚函数的继承结构来的,将基类指针转换为想要的子类指针。
Static_cast:范围更广的转换,必须是相关类型。
Const_cast:常量转型,其他类型可以转为const类型,但是const转为非const不行。
例:GraduateStudet gs(“smith”);
Student* ps = static_cast
若两类无关,而又不失void指针,则不可以转换,转后变为0。
抽象类:
抽象类专门用来被继承,天生用来当爹的,不能创建对象。抽象类不应该有构造函数。
抽象类至少定义一个纯虚函数(不具体实现的虚函数),专门为子类多态留下的接口。
纯虚函数定义:virtual void fun() = 0;,
只要是子类还有没覆盖的纯虚函数,则该子类仍可以作为抽象类被继承并覆盖抽象类。
可扩展性:class B:public A{Virtual newFun();} 其中A为原先实现的功能,扩展新功能。
模板:
函数模板:
Template
返回类型 函数模板名(数据参数表)
{
函数模板定义体。
}
注意:类型匹配非常严格,如果类型不一致就会编译错误,必须精确匹配。
类模板:
Template
Struct Node
{
Node(T& d):data(d),next(0),pref(0){}
T data; Node *next, *pref;
}
Template
Class List
{
Node
Public:
List();
Void add(T& data);
Void remove(T& data);
Node
Void print();
~List();
}
Template
Void List
模板类:template List< int>; List
组织形式:模板定义与模板使用在同一个便宜单位中,一般将模板定义与实现都在头文件中。
或者将模板定义与实现分开,头文件是定义,源文件为实现方法。(需要加export)
模板的多态:多态通过虚函数实现,动多态。
函数模板实现多态:编译时刻进行静态识别,静多态。
Template
Void fun(T& a){ ..... }
动多态:类层次结构,基类必须为多态类,含有虚函数等,多态函数单独在外面实现。
静态类:适合于所有累,不需要虚函数。通过函数模板实现。
Java中都是动多态,虚函数实现。抽象编程动多态更好些,实现雨啊代码隐蔽无需提供给用户。性能上静多态优于动多态。静多编译前就知道,调试方便。
泛型编程://模板编程 ,STL就是基于模板的框架类库。
异常
C中全局变量errno,专门用于存放错误代码。
框定异常:try
定义异常:catch
抛掷异常:throw