zoukankan      html  css  js  c++  java
  • C++学习随笔之七:对象和类

    这部分是c++升级c的主要内容,也是c++的精髓部分,c是面向过程的,而C++是面向对象的。面向对象编程(OOP)的最重要特性有:

    *抽象

    *封装和数据隐藏

    *多态

    *继承

    *代码的可重用性

    1.抽象和类:

    C++中的类,是一种将抽象将抽象转换为用户定义类型的C++工具(其他面向对象语言也类似,如java),它将数据表示和操纵数据的方法组合成一个整

    洁的包。

    定义类的规范有两个部分:类声明和类方法定义。

    类声明:以数据成员的方式描述数据部分,以成员函数(也成为方法)的方式描述公有接口。

    类方法定义:描述如何实现类成员函数。

    简单地说就是,类声明提供了类的蓝图,而类的方法定义则提供了实现细节。

    对类成员的控制访问:由于隐藏数据时oop的主要目标之一,所以数据项通常放在私有部分(private),组成类接口的成员函数放在公有部分,否则就无

    法从程序中调用这些函数,一般使用私有成员函数来处理不属于公共接口的实现细节。有时候不必使用private关键字,因为C++中,private是类对象默认  

      访问控制。

      现在学了类了,对类和结构的区别有了更进一步的了解:实际上类是对结构的扩展,他们有很多的相同特性,唯一区别是,结构的默认访问控制室public,

       类是private的。注意:结构体也可以定义方法:例如如下:

    public struct Person

    {

          string name;

    double height;

    double weight;

    public void OverWeight()

    {

    .....

      }

    }

      成员函数的定义:与常规函数定义非常相似,但是有两个特色的特征:

       (1)定义成员函数是,使用作用域解析操作符(::)来标识函数所属的类

       (2)类方法可以访问类的private组件

    代码示例:

    #include<iostream>

    #include<cstring>

    using namespace std;

    //类声明 

    class Stock 

    {

    private:

        char company[30];//公司名称 

        int shares;//所持股票的数量 

        double share_val;//每股的价格 

        double total_val;//股票总值 

        void SetTol()//这是个内陆函数 

        {

            total_val=shares*share_val; 

        }

    public:

        void Acquire(const char *co,int n,double pr);//获得股票 

        void Buy(int num,double price);//增持股票 

        void Sell(int num,double price);//卖出股票 

        void Update(double price);//更新股票价格 

        void Show();//显示关于所持股票的信息 

    };

    //定义类的成员函数

    void Stock::Acquire(const char *co,int n,double pr)

    {

    strncpy(company,co,29);

    company[29]='\0';

    if(n<0)

    {

        cerr <<"股票数量不能为负的!"<<endl;

        cerr <<company<<"的股票数量设置为0"<<endl;

        shares = 0; 

    }

    else

        shares = n;

    share_val = pr;

    SetTol();

    void Stock::Buy(int num,double price)

    {

    if(num<0)

    {

        cerr<<"增持股票数量不能为负的!"<<endl;

    }

    else

    {

        shares +=num;

        share_val=price;

        SetTol();

    }

    void Stock::Sell(int num,price)

    {

    if(num<0)

    {

        cerr<<"卖出股票数量不能为负的!"<<endl;

    }

    if(num>shares)

    {

        cerr<<"你卖出的股票数量不能大于你所持有的数量"<<endl;

    }

    else

    {

        shares = shares - num;

        share_val=price;

        SetTol();

    }

    }

    void Stock::Update(double price)

    {

    share_val=price;

    SetTol();

    void Stock::Show()

    {

    cout <<"company: "<<company;

    cout <<"  shares: "<<shares<<endl;

    cout <<"share price:$"<<share_val;

    cout <<"total Worth:$"<<total_val<<endl;

    }

       cerr对象:和cout对象一样,也是一个ostream对象,之间的区别在于,操作系统重定向只影响cout,而不影响cerr。cerr对象用于错误信息

    内联方法:在类声明中定义的的函数都将自动成为内联函数。因此以上SetTol()函数就是内联函数

    注意:调用成员函数时,它将使用被用来调用它的对象的成员数据。所创建的对象都有自己的存储空间,用于存储其内部变量和类成员;但同一个累的 所有对象共享同一组类方法,集每个方法(函数)只有一个副本。

    2.类的构造函数和析构函数:

    构造函数:是创建对象是自动调用的,但是不能通过对象来调用构造函数。还有就是不能将类成员名称用作构造函数的参数!

    析构函数:用构造函数创建对象后,程序负责跟踪该对象,直到其过期为止。对象过期时,程序将自动调用一个特殊的函数来完成清理工作,这个函数就是析构函数

    代码示例:

    stock.h文件代码:

    #include<iostream>

    #include<cstring>

    using namespace std;

    //类声明 

    class Stock 

    {

    private:

        char company[30];//公司名称 

        int shares;//所持股票的数量 

        double share_val;//每股的价格 

        double total_val;//股票总值 

        void SetTol()//这是个内陆函数 

        {

            total_val=shares*share_val; 

        }

    public:

        Stock();

        Stock(const char *co,int n,double pr);

        ~Stock();

        void Acquire(const char *co,int n,double pr);//获得股票 

        void Buy(int num,double price);//增持股票 

        void Sell(int num,double price);//卖出股票 

        void Update(double price);//更新股票价格 

        void Show();//显示关于所持股票的信息 

    };

    stock.cpp文件代码:

    #include<iostream>

    #include<cstring>

    #include"stock.h"

    using namespace std;

    //类的实现 

    //定义类的成员函数

    Stock::Stock()//默认构造函数 

    {

    cout<<"Default constructor called:"<<endl;

    strcpy(company,"noname");

    shares=0;

    share_val=0.0;

    total_val=0.0;

    }

    Stock::Stock(const char *co ,int n,double pr)//构造函数 

    {

    cout<<"Constructor using:"<<endl;

    strncpy(company,co,29);

    company[29]='\0';

    if(n<0)

    {

        cerr <<"股票数量不能为负的!"<<endl;

        cerr <<company<<"的股票数量设置为0"<<endl;

        shares = 0; 

    }

    else

        shares = n;

    share_val = pr;

    SetTol();

    }

    Stock::~Stock()//析构函数

    {

    cout<<"bye, "<<company<<"!"<<endl;//输出只是为了了解什么时候析构函数被调用。

    }

    void Stock::Buy(int num,double price)

    {

    if(num<0)

    {

        cerr<<"增持股票数量不能为负的!"<<endl;

    }

    else

    {

        shares +=num;

        share_val=price;

        SetTol();

    }

    void Stock::Show()

    {

    cout <<"company: "<<company;

    cout <<"  shares: "<<shares<<endl;

    cout <<"share price:$"<<share_val;

    cout <<"  total Worth:$"<<total_val<<endl;

    cout <<endl; 

    }

    main.cpp文件代码:

    #include <cstdlib>

    #include <iostream>

    #include<cstring>

    #include"stock.h" 

    using namespace std;

    int main(int argc, char *argv[])

    {

    cout.setf(ios_base::fixed);//格式化 

    cout.precision(2);//格式化 

    cout.setf(ios_base::showpoint);//格式化 

    cout<<"Using constructor to new objects:"<<endl;

    Stock stock1("NanoSmart",12,20.0);

    stock1.Show();

    Stock stock2=Stock("Boffo Objects",2,2.0);

    stock2.Show();

    cout<<"Assigning stock1 to stock2:"<<endl;

    stock2=stock1;

    cout<<"Listing stock1 and stock2:"<<endl;

    stock1.Show();

    stock2.Show();

    cout<<"Using a constructor to reset an object:"<<endl;

    stock1=Stock("Nifty Food",10,50.0);

    cout<<"Revised stock1:"<<endl;

    stock1.Show();

    cout<<"Done\n";

    return 0;

    }

    以上三个文件编译连接运行后的结果如下:

     

    想想结果为什么会这样??  

    const 成员函数:将const放在类函数之后,如 void Show()const,这样定义就是const成员函数,一般情况下,只要类方法不修改对象,则就应该将其声明为const。  

    构造函数的特例:接受一个参数的构造函数允许使用赋值句法来将对象初始化一个值,如构造函数原型为:Bob(int age);

    则可以这样初始化:Bob czm=22;这是第三种初始化对象的方法。

    3.this指针:指向用来调用成员函数的对象(this被作为隐藏参数传递给方法)。每个成员函数(包括构造函数和析构函数)都有一个this指针,this指针指向调用对象,this也是一个指针,所以和一般的指针一样,*this指针指向的值。

    代码示例:

    const Stock& Stock::Topval(const Stock & s) const 

    {

    if (s.total_val>total_val)

        return s;

    else

        return *this;

    }

    4.对象数组:要创建类对象数组,这个类必须有默认构造函数。因为初始化对象数组时,首先使用默认构造函数创建数组元素,然后花括号中的构造函数将创建临时变量,然后将临时变量的内容复制到相应的元素中。如:Stock stk[4] = {Stock("caizhiming",2,20),Stock("caizhicong"),Stock("caizhiming2",333,34),};

    现在对this指针比较了解了,现在深入了解C++的工作方式,比如C++前端cfront将c++程序转换为c程序:处理方法的定义时,只需将下面C++的定义:

    void Stock::Show()const

    {

    cout <<"company: "<<company;

    cout <<"  shares: "<<shares<<endl;

    cout <<"share price:$"<<share_val;

    cout <<"  total Worth:$"<<total_val<<endl;

    }

    转换为类C风格的定义:

    void Show(const Stock *this)

    {

    cout <<"company: "<<this->company;

    cout <<"  shares: "<<this->shares<<"\n";

    cout <<"share price:$"<<this->share_val;

    cout <<"  total Worth:$"<<this->total_val<<"\n";

    }

    同样的,将top.Show()转换为Show(&top)

    5.小结:

    面向对象编程强调的是程序如何表示数据。类是用户定义的类型,而对象则是类的实例,即对象是这种类型的变量。如果希望成员函数对多个对象进行操作,则可以将额外的对象作为参数传递给它。如果方法需要显示的引用调用它的对象,则可以使用this指针。

  • 相关阅读:
    【BZOJ4903】
    nuxt中引入svg
    vue-spa微信分享,在ios端,分享不成功的原因及解决办法
    安装包
    nuxt中刷新页面后防止store值丢失
    nuxt项目如何设置代理接口
    nuxt引入jquery和bootstrap
    如何在nuxt中引入scss
    创建nuxt项目
    微信分享
  • 原文地址:https://www.cnblogs.com/JczmDeveloper/p/2964810.html
Copyright © 2011-2022 走看看