Chinaunix首页 | 论坛 | 博客
  • 博客访问: 208450
  • 博文数量: 37
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 375
  • 用 户 组: 普通用户
  • 注册时间: 2015-04-23 21:00
个人简介

潜心静气。。慢慢出成果

文章分类

全部博文(37)

文章存档

2018年(5)

2017年(6)

2016年(23)

2015年(3)

我的朋友

分类: C/C++

2016-09-30 11:06:42

研究了C++的数据封装后,突然领悟C++的视角应该是数据封装,继承派生,和重载。用这种思路来学习C++ ,而不是一头埋进代码里,学习还是要搞清楚架构,然后往里面填砖即可。下边就开始了我的C++的总结之路:
心情蛮有期待,首先在C语言中的定义在C++中依然可以使用,C++中class类的封装和普通函数并存,只是封装成了主角,好比是C中结构体也只是占一部分而已。
不过话说C++是从C语言中演变而来,确实不假,C语言中的结构体用到了极致就是面向对象了。
言归正传:
定义一个简单的类 class +name
封装的三种属性:public 可以被外界函数访问,private:只能被class内部函数访问,protected:也是只能被class内部函数访问,那有个小小的问题,private 和protected的效果不就是个矛盾体了?
我相信C++的精简极致,,一定是有用处的,查看资料发现在继承和派生处 ,protected和private的的意义是不一样的,当不向外部暴露某个函数或者成员变量,但又想让派生类知道和访问这个成员,这是用处有了。OK待到派生和继承时在叙述。
class的封装分为数据的封装和函数的封装:
数据的封装按照我的理解可以分为:C语言的基本数据类型,和C++的衍生出来的数据类型,别笑话,学过C语言,因此依靠C语言作为载体快速记忆,会快点。
C语言的基本数据类型:
char short int long double float 
数组:
同一数据类型的几个数组成的集合,依然可以采用跟C中的类似用法,如char str[10],定义一个含义10个元素的字符数组
指针当然也可以定义,如char *p;
在C语言中的组合数据类型如;结构体,枚举型,联合体,等在C++中也是可以用,只是没有用的必要了。
还有一个数据的封装类型为类对象。
类对象可以当成一个普通的数据类型来使用,可以用类对象来定义对象,也可以直接赋值,或者作为函数的返回值,形参等。
#include
using namespace std;
class CDate
{
public:
    CDate(int ,int ,int );
    CDate(CDate &c);
    ~CDate();
private:
    int year;
    int month;
    int day;
};
class CStudentID
{
public:
    CStudentID(int i,int d);
    void print() const;
    ~CStudentID();
private:
const int id;
int di;
};
class CStudent
{
public:
    CStudent(string ,CDate &,CStudentID &);
    ~CStudent();
    //static int search(CStudent &s);
    void print(CStudent *);
private:
    string name;
    static int stu_num;
    CDate c;
    CStudentID s;
};
具体事例如下:
这个事例中包含了上述的讲述,依照事例来进行讲解,讲解的思路就是每一项的定义,初始化,调用的思路进行叙述。
基本数据类型定义:属性为public时,可以被外界函数访问,不过好像没有必要,class的目的就是为了封装数据,不让外界触碰到数据。一般是定义为private:
只能被class内部成员函数访问,初始化时可以用构造函数或者直接在内部成员函数直接赋值。
基本数据成员可以被修饰程const 或者static
被修饰成const是就是常数据成员,可以被类内函数访问,但不能修改,其初始化时只能用析构函数的成员列表的方式进行访问如:
CStudentID::CStudentID(int i,int d):id(i) id就是CStudentID 的一个private const数据成员。
使用时可以被const函数访问,也可以被非const函数访问,不能修改其数值。
static修饰时表示为静态成员数据,静态数据是属于类,而不属于任何一个类对象,因此所有对象共享static数据的一块内存。
定义方式是:int CStudent::stu_num=0;
直接在函数外不是在构造函数内。
数组的组合数据在class内封装时,用法跟C语言一样,访问方式也跟基本数据类型一样。
定义如下:private int[] array; 
除上诉之外,还有一个新的数据是string,字符串类型,不过这个类型的数据在使用之前需要加入
#include
using namespace std;
不然会报错。
类对象也可以作为数据封装到类中。如下:
private:
    string name;
    static int stu_num;
    CDate c;
    CStudentID s;
在使用构造函数初始化时,注意也只能使用参数列表的方式:
CStudent::CStudent(string str,CDate &cd,CStudentID &cs):c(cd),s(cs)
具体使用则在文章最后讲述类对象如何使用。
class的成员还有函数。
函数中有析构函数和构造函数,以及拷贝构造函数。
析构函数:每个类定义封装时一定存在析构函数,如果没有自定义,则会默认为空。
声明方式:    ~CStudent();
定义方式:
CStudent::~CStudent()
{
    cout<<"CStudent::destruct"< }
析构函数在对象生存期结束时自动调用。析构函数和构造函数,拷贝构造函数属性只能为public。


构造函数:如果用户未自定义时,默认为空。
如果用户定义多个构造函数,则会按照参数列表的规则进行比较。执行匹配的构造函数。
声明如下:
CDate(int ,int ,int );
定义如下:
CDate::CDate(int y=1991,int m=12,int d=12)
{
    year=y;mounth=m;day=d;
    cout<<"CDate:: construct"< }
构造函数的执行也是在创建对象时自动执行。
不过构造函数和析构函数的执行顺序是反的,即构造函数先执行,析构函数则是后执行。
构造函数还可以采用参数列表法来初始化。上述的例子可以改为:
CDate::CDate(int y=1991,int m=12,int d=12):year(y),mounth(m),day(d){}
不过声明是也还是一样的。
对于参数列表方式初始化数据成员的构造函数,如果用户定义多个构造函数,而且使用缺省参数时,会出现二义性,无法判断哪个构造函数使用对象。
拷贝构造函数如果用户未定义时,则不为空,其实现的作用是讲对象的所有数据成员都拷贝到新创建的对象中去。
拷贝构造函数的声明方式:
CDate(CDate &c);
定义:
CDate::CDate(CDate &c)
{
  year=c.year;mounth=c.mounth;day=c.day;
  cout<<"CDate:: copy construct"< }
使用:
在 对象创建对象时,比如CDate c(s);s为已创建对象,
或者直接CDate s=c;
对象数据类型作为形参或者返回值时,会自动调用拷贝构造函数。
static和const也可以修饰函数。
const修饰函数时,可以访问非cosnt数据成员,和const数据成员,不过不能修改任何数据。
声明
 void print() const;
定义
 void CStudentID::print() const
{
    cout<<"id="<     cout<<"di="< }
const成员函数可以被任何类对象访问,不过const对象只能访问const成员函数。
static修饰成员函数时,则是分为pulic还是protected private类,如果是public属性,则被对象访问时可以指定对象,比如
CStudentID stu;
stu.print();也可以CStudentID::print();因为static类型不属于任何的对象,如果是proetcted private时,只能适用对象访问。
其中静态成员函数只能访问静态数据,不能访问非静态数据,如下:
class CMystring
{
public:
static int get_total_len()
{
total_len+=len;
return total_len;
}


private:
static int total_len;
int len;
}
此时数据的访问就会出错,因为len为非静态数据成员,可以更改为:
class CMystring
{
public:
static int get_total_len(CMystring str)
{
total_len+=str.len;
return total_len;
}


private:
static int total_len;
int len;
}
对象的创建和执行。
对象创建时分为对象变量
CStudentID id1(12,21);
id1.print();
对象指针:
CStudentID id1(12,21);
CStudentID *p;
p=&id1;
p->print();
对象引用:
CStudentID &id2=id1;
id2.print();
对象创建时还可以用new来创建,用delete来删除。
CStudentID *id_p=new CStudentID(33,44);
id_p->print();
delete id_p;
如果对象被const修饰时,则是只能调用const函数,访问别的函数会报错。
const CStudentID id4(55,66);
    id4.print();const函数
    id4.print_t();非const 函数。
package.cpp:67:17: error: passing ‘const CStudentID’ as ‘this’ argument of ‘void CStudentID::print_t()’ discards qualifiers [-fpermissive]
顺便加点友元函数和友元类:
友元函数:由于类具有封装性和数据的隐蔽性,程序中的其它函数无法访问类的私有成员,如果定义公有,则破坏了类的封装性,因此引入了累的友元函数
友元函数:在类外定义的函数,可以使普通函数,也可以是其他类的成员函数,定义为友元函数后则就可以访问该类的数据成员。
定义如下:
friend void printf(CDate *p);
void printf(CDate *p)
{
cout<<"data" }


友元类:友元还可以是个类,一个类作为另外一个类的友元时,意味着这个类的成员函数都是这个类的友元函数,可以访问这个类的私有数据。
class A
{


}
class B
{
public:
friend class A 
则A是B的友元类,A的成员函数都是B的友元函数,B的私有数据都可以被A的成员函数访问。
}
现贴出整个过程中的调试代码。本文章仅作为自己的学习笔记和总结,如果错误的地方欢迎指出。
#include
using namespace std;
class CStudentID
{
public: 
    friend class CStudent; 
    CStudentID(int i,int d);
    void print() const;
    void print_t();
    ~CStudentID();
private:
const int id;
int di;
};
class CDate
{
public:
    friend class CStudent; 
    CDate(int ,int ,int );
    CDate(CDate &c);
    ~CDate();
    friend void printf(CDate *p);
private:
    int year;
    int month;
    int day;
};
void printf(CDate *p);
class CStudent
{
public:
    CStudent(string ,CDate &,CStudentID &);
    ~CStudent();
    //static int search(CStudent &s);
    void print(CStudent *,CDate *,CStudentID *);
private:
    string name;
    static int stu_num;
    CDate c;
    CStudentID s;
};
#include
#include "package.h"


CDate::CDate(int y=1991,int m=12,int d=12)
{
    year=y;month=m;day=d;
    cout<<"CDate:: construct"< }
CDate::CDate(CDate &c)
{
  year=c.year;month=c.month;day=c.day;
  cout<<"CDate:: copy construct"< }
CDate::~CDate()
{
    cout<<"CDate::destruct"< }
CStudentID::CStudentID(int i,int d):id(i)
{
    di=d;
    cout<<"CStudentID::construct"< }
 void CStudentID::print() const
{
    cout<<"id="<     cout<<"di="< }
void CStudentID::print_t()
{
    cout<<"id="<     cout<<"di="< }
CStudentID::~CStudentID()
{
    cout<<"CStudentID::destruct"< }
int CStudent::stu_num=0;
CStudent::CStudent(string str,CDate &cd,CStudentID &cs):c(cd),s(cs)
{
    stu_num++;
    name=str;
}
CStudent::~CStudent()
{
    cout<<"CStudent::destruct"< }
void CStudent::print(CStudent *pst,CDate *pda,CStudentID *pid)
{
    cout<<"friend" }
void printf(CDate *p)
{
    cout<<"data" }
int main(void)
{
    CDate date1(2011,12,12);
    printf(&date1);
    CStudentID id1(12,21);
    id1.print();
    CStudentID *p;
    p=&id1;
    p->print();
    CStudentID &id2=id1;
    id2.print();
    CStudentID *id_p=new CStudentID(33,44);
    id_p->print();
    delete id_p;
    const CStudentID id4(55,66);
    id4.print();
    CStudent stu1("zhang",date1,id1);
    stu1.print(&stu1,&date1,&id1);
    return 0;
}
阅读(2043) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~