前言
"打牢基础,万事不愁" .C++的基础语法的学习."学以致用,边学边用",编程是实践性很强的技术,在运用中理解,总结.
引入
类是面向对象的基本构成部分,对象与对象之间常产生数据的传递.本贴和另一个贴C++基础语法:类包含_c++中的包括怎么写-优快云博客有一些关系,也会实现另一个帖子C++基础语法:STL之迭代器_stl迭代器-优快云博客中没有实现的迭代器.对象之间数据传递主要是通过包含来实现的(继承天然是派生类也可以使用基类数据,主要是接口的继承,范围更广).而迭代器的实现是一个综合型的数据传递的示例.
对类静态数据,枚举也做一些分析.
静态数据
静态数据是属于类的,对象数据是属于对象的.静态数据也有静态属性和静态函数;
静态数据用static修饰,如static int number;
类和对象是类型和变量的关系.类先于对象存在,所以静态数据可以被对象所使用.举例:
class Demo{
static int number; //静态变量
static int getNumber(); //静态函数
private:
int id;
public:
Demo():id(number++){} //对象构造函数,有静态变量参与
int getId() const{return id;} //获得对象id
}
Demo类声明了静态数据number,每次生成对象时,id自动+1,实现给每个对象编号.
概念:发消息-----本书有概念:在OOP中,对象之间的交互称作发消息.当程序员把这一概念应用到类中,可以得到相似的概念:静态变量在对象和类之间传递消息,静态函数在对类以外传递消息.比如在类外面调用接口函数Demo::getNumber(),可以获得Demo类的对象个数.而调用每个对象的getId()可以获得是该类中的第几号对象.
思考:静态函数的一般要和类相关.如果普通函数可以完成的,一般不用静态函数.这和"数据私有,接口公开"一样是在编程过程中潜移默化形成的
类中使用的枚举---对象的静态数据
不管是三种枚举中的哪一种,都可以被视为对象使用的"静态常量".他是每个对象拥有的,并且可以被用在构造函数中,相当于对象使用的静态数据,在<C++ Prime Plus> 6th Edition上找两个用法,如下所示
1. 对象有整型属性,以枚举值为默认参数.
//说明枚举用法举例,非vector容器定义
template<class T>
class vector{
int vector_size; //vector容器长度
public:
enum{MAX=10} //默认最大值
vector(int vec_size=MAX):vector_size(vec_size){}: //默认参数传给对象属性
}
====================
vector<int> vt; //默认10个int类型数据
vector<int> vt(20); //20个int类型数据,覆盖MAX
2.对象有枚举属性,初始化时传入
下面是个表示物体的类,声明了枚举类型MODE,在属性中定义了MODE变量mode,用于表示当前物体所处状态,默认直角坐标系REC.当切换坐标系后,相应数据作出变化(未展开)
class Obj{ //物体类
MODE mode; //枚举变量,表示物体坐标状态
int rec_x; //直角坐标系x值
int rec_x; //直角坐标系x值
double polar_length; //极坐标系长度值
double polar_angle; //极坐标系角度值
public:
enum MODE{REC,POLAR}; //枚举声明
Obj(MODE mo=REC,int x,int y)
:mode(mo),rec_x(x),rec_y(y){}; //构造函数,默认直角坐标系REC
... //其他
}
======================
Obj obj(3,5); //调用构造函数生成物体,坐标(3,5)
上面演示了两种枚举做对象静态变量的代码写法.
对象传递
对象之间数据传递有两种办法:类包含和类A对象方法返回值是B对象类型
前提:被包含的对象所在的类要能"被看见",所在.h头文件包含进当前文件
1.类包含
C++基础语法:类包含_c++包含-优快云博客 对类包含有叙述,用代码描述如下
//被包含类定义
class T{
int age;
public:
T(int ag):age(ag){};
int getAge(){return age;}
}
//包含类定义
class Contain{
T& t;
public:
Contain(T& val):t(val){};
int getAge(){return t.getAge();}
}
对象多数以引用&形式传入,提供对原有数据的访问和修改权限;如果不想被修改,使用const修饰.如
//包含类定义
class Contain{
const T& t; //类型与构造函数匹配
public:
Contain(const T& val):t(val){}; //传入对象被限制,只能读取不能修改
int getAge(){return t.getAge();}
}
使用对象指针也可以,一般指针代表集合,不代表单个对象.这和"数据私有,接口公开"一样,属于"默认"行为.就算是为了节省空间,传入new堆空间分配内存使用的指针,也是不推荐的.使用引用类型代表单个对象
类包含还可以使用被包含对象的多种形式,视表达需要
//包含类定义
class Contain{
T& t; //对象引用
T ar[10]; //对象数组
T* pt; //对象指针
T** ppt; //对象双重指针
vector<T> vt;//对象容器
}
2.类A对象方法返回值是B对象类型
除了类A包含其他类对象B,使被包含对象B能被访问和修改,另一种办法是在类A中定义对象方法,该方法的返回值类型为B.如
//伪代码
class B{};
class A{
public:
B fun(){
... //语句
return B对象 //返回B对象
}
}
这种写法的好处是避开"相互包含".如果两个类互相包含对方的对象,会产生"先有鸡还是先有蛋"的逻辑问题,所以应该被避开.那么两个对象怎样实现数据的交互呢,可以采用一个用类包含,一个用对象方法返回值类型设定为另一个类的类型的方式.
迭代器即是上述方法的综合使用.
小结
类数据的传递