类和构造函数

什么是类

  • 类是定义同一类所有对象的变量和方法的蓝图或原型
#include<stdio.h>
#include<iostream>
using namespace std;
class Person
{
private://访问修饰符
        int id;
        int money;
public:
      void show()
      {
            cout<<"id = "<<id<<" money = "<<money<<endl;
      }
      void set(int a,int b)
      {
        if(a<0)
        {
            a=0;
        }
        id=a;
        money=b;
     }
};
int main()
{
    class Person a;
    class Person b;
    a.set(1,1000);
    a.show();
    b.set(2,100);
    b.show();
}

  • C++的类与结构的区别
  • 在面向对象中,算法与结构体被捆绑在一起

定义成员函数

  1. 在类中定义成员函数
  • 类中定义的成员函数一般为内联函数,即使没有明确用inline标示
  • 在C++中,类定义通常在头文件中,因此这些成员函数定义也伴随着进入头文件
  1. 在类之后定义(一个类占一个.h配一个.c)
  • C++允许在其它地方定义成员函数。
  • 将类定义和其成员函数定义分开,是目前开发程序的通常做法。
  • 我们把类定义(头文件)看成是类的外部接口,类的成员函数定义看成是类的内部实现。
#include<stdio.h>
#include<iostream>
using namespace std;
class Person
{
private:
        int id;
        int money;
public:
      void show();
      void set(int a,int b);
};
void Person::show()
{
    cout<<"id = "<<id<<" money = "<<money<<endl;
}
void Person::set(int a,int b)
{
    if(a<0)
    {
        a=0;
    }
    id=a;
    money=b;
}
int main()
{
    class Person a;
    class Person b;
    a.set(1,1000);
    a.show();
    b.set(2,100);
    b.show();
}

//结果为: id = 1 money = 1000
//id = 2 money = 100;

#include<iostream>
using namespace std;
class Person
{
private:
        int id;
        int money;
public:
      void show();
      void show(int x);
};
void Person::show()
{
    cout<<"Person show void"<<endl;
}
void Person::show(int x)
{
    cout<<"Person show "<<x<<endl;
}
void show()
{
    cout<<"show void"<<endl;
}
class Test
{   
public:
      void show()
      {
        cout<<"Test show void "<<endl;
      }
};
int main()
{
    class Person a;
    a.show();
    a.show(100);
    class Test b;
    b.show();
}

//结果为:Person show void
//Person show 100
//Test show void


#include<iostream>
using namespace std;
class Test
{   
public:
      void show()
      {
        cout<<"Test show void "<<endl;
      }
};

void lianxi1(Test *p1)
{
    p1->show();
}
void lianxi2(Test &p2)
{
    p2.show();
}
void lianxi3(Test p3)
{
    p3.show();
}
int main()
{
    Test t;
    lianxi1(&t);
    lianxi2(t);
    lianxi3(t);
}
//结果为 Test show void
//Test show void
//Test show void

#include<iostream>
using namespace std;
class Test
{   
      int id;
public:
      void setid(int i)
      {
        id=i;
      }
      void show()
      {
        cout<<"this"<<(this)<<endl;
        cout<<"id = "<<this->id<<endl;
      }
};
int main()
{
    Test t;
    t.setid(222);
    t.show();
    cout<<"&t = "<<&t<<endl;
}

//结果为:this 0x50
//&t = 0x50
//id = 222

封装(数据是私有的,函数是公有的)

  1. 类的封装的概念首先是,数据与算法(操作)结合,构成一个不可分割的整体(对象)。
  2. 其次是,在这个整体中—些成员是被保护的,它们被有效地屏蔽,以防外界的干扰和误操作。
  3. 另一些成员是公共的,它们作为接口提供给外界使用。而对该对象的描述即是创建用户定义的类型,对C++来说,就是类的实现机制.

类的作用域

  • 一个类的所有成员位于这个类的作用域内
    类作用域是类定义和相应类成员定义范围
  • ::前面要加类名

封装的优点

  1. 重用
  2. 不必关心具体的实现
  3. 具有安全性

构造函数

  • C++的构造函数和析构,使得类对象能够轻灵地被创建和撤销
  1. 构造函数创建类对象,初始化其成员
  2. 析构函数撤销类对象
  3. 构造函数和析构函数是类的特殊成员函数
  • 类的对象的初试化只能由类的成员函数来进行
  1. 建立对象的同时,自动调用构造函数
  2. 类对象的定义涉及到一个类名和一个对象名
    由于类的唯一性和对象的多样性,用类名而不是对象名来作为构造函数名是比较合适的

练习题

  1. 建立一个时钟,显示时间
#include<iostream>
#include<stdlib.h>
#include<unistd.h>
using namespace std;
class Clock
{
    int hour;
    int minute;
    int second;
public:
    void setTime(int h,int m,int s)
    {
        hour=h;
        minute=m;
        second=s;
    }
    void show()
    {
        cout<<hour<<":";
        cout<<minute<<":";
        cout<<second<<endl;
    }
    void tick()
    {
        sleep(1);
        if(second==59&&minute!=59)
        {
            minute=minute+1;
            second=1;
        }
        else if(minute==59&&second==59&&hour!=23)
        {
            hour=hour+1;
            minute=0;
            second=1;
        }
        else if(hour==23&&minute==59&&second==59)
        {
            hour=0;
            minute=0;
            second=1;
        }
        else
        {
            second=second+1;
        }
    }
    void run()
    {
        while(1)
        {
            system("clear");
            show();
            tick();
        }
    }
};
int main()
{
    Clock clock;
    clock.setTime(23,59,50);
    clock.run();        
}

  1. 建立一个分数
#include<iostream>
using namespace std;
class Fraction
{
    int m;
    int n;
public:
    void setNum(int i,int j)
    {
        m=i;
        n=j;
    }
    void reduce()
    {
        int i;
        int min=m<n?m:n;
        for(i=min;i>0;i--)
        {
            if(m%i==0&&n%i==0)
            {
                break;
            }
        }
        m=m/i;
        n=n/i;
    }
    void show()
    {
        reduce();
        if(m%n==0)
        {
            cout<<"m = "<<m<<endl;
            cout<<"n = "<<n<<endl;
            cout<<"m/n = "<<m<<endl;
        }
        else
        {
            cout<<"m = "<<m<<endl;
            cout<<"n = "<<n<<endl;
            cout<<" m/n = "<<m<<"/"<<n<<endl;
        }
    }
};
int main()
{
    Fraction a;
    int c,b;
    cin>>c>>b;
    a.setNum(c,b);
    a.show();
}

构造函数(析构函数是成员函数)

  • 使得类对象能够轻易地被创建和撤销
#include<iostream>
using namespace std;
class Fract
{
    int m_m;
    int m_z;
public:
      Fract()
      {
        m_m=16;
        m_z=48;
      }
      void set(int m,int z)
      {
        m_m=m;
        m_z=z;
      }
      void print()
      {
        reduce();
        cout<<m_z<<"/"<<m_m<<endl;
      }
      void reduce()
      {
        for(int i=m_m;i>0;i--)
        {
            if((m_m%i==0)&&(m_z%i==0))
            {
                m_m/=i;
                m_z/=i;
                break;
            }
        }
      }
};
int main()
{
    Fract a;
    a.print();
}
//没有了a.set,结果为3/1;

  • 第三形态
#include<iostream>
using namespace std;
class Fract
{
    int m_m;
    int m_z;
public:
      Fract();
      void set(int m,int z)
      {
        m_m=m;
        m_z=z;
      }
      void print()
      {
        reduce();
        cout<<m_z<<"/"<<m_m<<endl;
      }
      void reduce()
      {
        for(int i=m_m;i>0;i--)
        {
            if((m_m%i==0)&&(m_z%i==0))
            {
                m_m/=i;
                m_z/=i;
                break;
            }
        }
      }
};
Fract::Fract()
{
    m_m=16;
    m_z=48;
}
int main()
{
    Fract a;
//  a.set(12,16);
    a.print();
}

  • 一步成型
#include<iostream>
using namespace std;
class Fract
{
    int m_m;
    int m_z;
public:
      Fract(int m,int z)
      {
        m_m=m;
        m_z=z;
      }
      void set(int m,int z)
      {
        m_m=m;
        m_z=z;
      }
      void print()
      {
        reduce();
        cout<<m_z<<"/"<<m_m<<endl;
      }
      void reduce()
      {
        for(int i=m_m;i>0;i--)
        {
            if((m_m%i==0)&&(m_z%i==0))
            {
                m_m/=i;
                m_z/=i;
                break;
            }
        }
      }
};
int main()
{
    Fract f1(10,20);
    f1.print();
    Fract f2(30,5);
    f2.print();
}

  • 成员函数的重载

#include<iostream>
using namespace std;
class Fract
{
    int m_m;
    int m_z;
public:
      Fract(int m,int z)
      {
        m_m=m;
        m_z=z;
      }
      Fract()
      {
        m_m=10;
        m_z=100;
      }
      void set(int m,int z)
      {
        m_m=m;
        m_z=z;
      }
      void print()
      {
        reduce();
        cout<<m_z<<"/"<<m_m<<endl;
      }
      void reduce()
      {
        for(int i=m_m;i>0;i--)
        {
            if((m_m%i==0)&&(m_z%i==0))
            {
                m_m/=i;
                m_z/=i;
                break;
            }
        }
      }
};
int main()
{
    Fract f1(10,20);
    f1.print();
    Fract f2;
    f2.print();
}

  • 数组
#include<iostream>
using namespace std;
class Fract
{
    int m_m;
    int m_z;
public:
      Fract(int m,int z)
      {
        m_m=m;
        m_z=z;
      }
      Fract()
      {
        m_m=10;
        m_z=100;
        cout<<"Fract construct"<<endl;
      }
      void set(int m,int z)
      {
        m_m=m;
        m_z=z;
      }
      void print()
      {
        reduce();
        cout<<m_z<<"/"<<m_m<<endl;
      }
      void reduce()
      {
        for(int i=m_m;i>0;i--)
        {
            if((m_m%i==0)&&(m_z%i==0))
            {
                m_m/=i;
                m_z/=i;
                break;
            }
        }
      }
};
int main()
{
    Fract f2[5];
}

//结果为:Fract construct
//Fract construct
//Fract construct
//Fract construct
//Fract construct

定义对象

对象的初始化

  1. 建立对象,须有一个有意义的初始值
    C++建立和初始化对象的过程专门由该类的构造函数来完成。
  2. 构造函数给对象分配空间和初始化。
  3. 如果一个类没有专门定义构造函数,那么C++就仅仅创建对象而不做任何初始化
  • 每一个类都要保证要有一个无参的构造函数
#include<iostream>
using namespace std;
class A
{   
public:
    A()
    {
        cout<<"A construct"<<endl;
    }
};
class Test
{
    A m_t;
public:
    Test()
    {
        cout<<"Test construct"<<endl;
    }
};
int main()
{
    Test t;

}

//结果为:Aconstruct
//Test construct

  • 一个类中的成员函数包含另一个类中的构造函数,则再创建类的空间时,都会创建
#include<iostream>
using namespace std;
class A
{
    int m_a;
public:
    A(int a)
    {
        m_a=a;
        cout<<"A construct "<<m_a<<endl;
    }
};
class Test
{
    A m_t;
public:
    Test():m_t(222)
    {
        cout<<"Test construct"<<endl;
    }
};
int main()
{
    Test t;

}

//结果为:A construct 222
//Test construct

#include<iostream>
using namespace std;
class A
{
    int m_a;
public:
    A(int a)
    {
        m_a=a;
        cout<<"A construct "<<m_a<<endl;
    }
    A()
    {
    }
};
class Test
{
    A m_t1;
public:
    Test():m_t1()
    {
        cout<<"Test construct"<<endl;
    }
};
int main()
{
    Test t;

}
//结果为:Test construct

  • 当含有多个成员变量时
#include<iostream>
using namespace std;
class A
{
    int m_a;
public:
    A(int a)
    {
        m_a=a;
        cout<<"A construct "<<m_a<<endl;
    }
};
class Test
{
    A m_t2;
    A m_t1;
public:
    Test():m_t1(111),m_t2(222)
    {
        cout<<"Test construct"<<endl;
    }
};
int main()
{
    Test t;

}

//结果为:A construct222
//A construct111
//Test construct

析构函数(有且只有一个)

#include<iostream>
using namespace std;
class A
{
    int m_a;
public:
    A(int a)
    {
        m_a=a;
        cout<<"A construct "<<a<<endl;
    }
};
class Test
{
    A m_t1;
    A m_t2;
public:
    Test():m_t2(222),m_t1(111)
    {
        cout<<"Test construct"<<endl;
    }
    ~Test()
    {
        cout<<"~~~~~~Test"<<endl;
    }
};
int main()
{
    Test t;
    cout<<"=========="<<endl;
}

//结果为:A construct 111
//A construct 222
//Test construct
//=================
//~~~~~~Test(在t消亡后才运行)

#include<iostream>
using namespace std;
class A
{
    int m_a;
public:
    A(int a)
    {
        m_a=a;
        cout<<"A construct "<<a<<endl;
    }
    ~A()
    {
        cout<<"~~~~~~A "<<m_a<<endl;
    }
};
class Test
{
    A m_t1;
    A m_t2;
public:
    Test():m_t2(222),m_t1(111)
    {
        cout<<"Test construct"<<endl;
    }
    ~Test()
    {
        cout<<"~~~~~~Test"<<endl;
    }
};
int main()
{
    Test t;
    cout<<"=========="<<endl;
}
//结果为:A construct 111
//A construct 222
//Test construct
//=================
//~~~~~~Test
//~~~~~~A 222
//~~~~~~A 111

#include<iostream>
#include<malloc.h>
using namespace std;
class Test
{
    int *p;
public:
    Test()
    {
        p=(int *)malloc(sizeof(int));
        *p=4;
        cout<<"Test construct "<<endl;
    }
    ~Test()
    {
        free(p);
        cout<<"~~~~~~~Test"<<endl;
    }
    void print()
    {
        cout<<*p<<endl;
    }
};
int main()
{
    Test t;
    t.print();
    cout<<"========="<<endl;
}

//结果为:Test construct
//4
//======================
//~~~~~~~~Test

  • 构造函数在分配空间之后调用

bool

#include<iostream>
using namespace std;
int main(int argc,char **argv)
{
    bool bSex=true;
    cout<<"请输入性别:";
    cin>>bSex;
    cout<<"我叫Jack,是一位"<<(bSex?"帅锅":"美女")<<endl;
    cout<<"true = "<<true<<endl;
    cout<<"false = "<<false<<endl;
    
}

#include<iostream>
using namespace std;
int main()
{
    string s;//string s("weiwei");//string s1(5,'a');//string s(s1);
    s="hello shangqian!";//1.赋值
    s+="sq1409";//2.追加/连接
//  s="hello";
//  s.clear();//清空
    cout<<"size = "<<s.size()<<endl;//求长度
    cout<<"s是否为空"<<(s.empty()?"空":"非空")<<endl;
    cout<<"s = "<<s<<endl;
    //string类型和char *类型的转换
    const char *buf=s.c_str();
    cout<<"buf = "<<buf<<endl;
    //字符串比较,可以直接用比较运算符//== != > <
    if(s=="hello")
    {
        cout<<"s == hello"<<endl;
    }
    //查看某个位置上的字符//at()越界访问 会抛出异常//[]不会
    cout<<"s[3] = "<<s[3]<<endl;
//  cout<<"s[4] = "<<s.at(4)<<endl;//可以通过异常捕捉
    return 0;
    
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 201,468评论 5 473
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,620评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,427评论 0 334
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,160评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,197评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,334评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,775评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,444评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,628评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,459评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,508评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,210评论 3 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,767评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,850评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,076评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,627评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,196评论 2 341

推荐阅读更多精彩内容

  • C++基础 类和构造函数 类 类:类是定义同一类所有对象得变量和方法的蓝图或原型。数据与算法的统一。成员成员函数保...
    I踏雪寻梅阅读 257评论 0 1
  • C++文件 例:从文件income. in中读入收入直到文件结束,并将收入和税金输出到文件tax. out。 检查...
    SeanC52111阅读 2,747评论 0 3
  • 本文博客园地址:http://www.cnblogs.com/xiongxuanwen/p/4290086.htm...
    先之阅读 828评论 0 5
  • 本章将会介绍 存储属性的初始赋值自定义构造过程默认构造器值类型的构造器代理类的继承和构造过程可失败构造器必要构造器...
    寒桥阅读 766评论 0 0
  • 窗外雨声唏哗 轻一下重一下 天边阴云游弋 四地烟笼雾起 你在街上是吗 记得带伞了吗 回忆如潮回起 旧事美妙无比 大...
    deepspring99阅读 268评论 0 2