类和对象

类介绍及其简单使用       

        c和c++最大的区别在哪里呢?c语言时面向过程的语言,c++是面向对象的编程。c++中也多了类的概念,类就是为了表示一类具有某些共同特性的对象。类中一般包括数据和类方法,类方法也就是要实现某些功能的函数,其实在c语言也可以实现类似功能,我们可以通过结构体的方式,类方法则可以通过函数指针来声明。但是结构体和类仍然有很多区别,类的功能更加丰富。

我们来看看下面的一个类,这个类是表示股票的一个类

class Stock
{
private:
        char company[30];
        int shares;
        double share_val;
        double total_val;
        void set_tot(){ 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();                                                                                                                                             
}

class 关键字标识类的定义。Stock是这个类的类型名。这样我们就可以用Stock声明Stock类型的变量,例如

Stock xiaomi;

Stock hengda;

创建两个Stock对象,他们分别名为xiaomi和hengda。

        接下来是要存储的数据,private表示接下来的数据和方法都是私有的,在类当中,默认的都是private,只能在类内部使用,若用public声明,则表示可以被外部类使用。

        private和public描述了对类成员的访问控制,使用类对象的程序都可以直接访问共有部分,但只能通过公有成员函数来访问对象的私有成员。例如Stock类中的share成员,外部程序是不能直接访问的,但是可以通过公有的成员函数来访问,公有函数是外部程序与类中的私有数据的桥梁。

        这样一个类的声明,我们通常放到头文件中,而类中方法的实现则放到c文件中,这和结构体类似。结构体的声明我们一般也是放到头文件中,结构体中定义的一些函数指针,则会在源文件中实现。结构体和类还有一点区别是,结构体中是无法声明私有数据的。

下面我们就实现类中定义的方法

定义类方法时,与定义普通的函数时有一个区别是,类方法的函数头使用作用域解析操作符(::)来指出函数所属的类。例如,Stock类的update方法的函数头如下:

void Stock::update(double price)

加::的作用是为了表明update函数是属于哪一个类的,因为又有可能有多个类中都有update方法,同样在类外部使用使用update方法时,也要用::指定是要使用哪一个类的update方法,当然,在Stock类内部时,可以直接使用update方法,不必加::

我们实现acuire方法

void Stock::acquire(const char *co,int n,double pr) 
{
        std::strncpy(company,co,29);
        company[29] = '\0';
        if (n < 0) {
                std::cerr << "num of shares can't be negative."
                        << company << "shares set to 0.\n";
                shares = 0;
        }
        else
                shares = n;
        share_val = pr; 
        set_tot();
}

我们可以看到,类内部的私有数据company,shares等都是可以在方法中进行操作的。

如何使用这个方法呢,需要首先创建一个Stock类对象,例如 Stock xiaomi,然后xiaomi.acquire就可以使用这个方法了。

我们看一个简单的例子

#include <iostream>
#include <cstring>
class Stock
{
        private:
                char company[30];
                int shares;
                double share_val;
                double total_val;
                void set_tot(){ 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) 
{
        std::strncpy(company,co,29);
        company[29] = '\0';
        if (n < 0) {
                std::cerr << "num of shares can't be negative."
                        << company << "shares set to 0.\n";
                shares = 0;
        }
        else
                shares = n;
        share_val = pr; 
        set_tot();
}
void Stock::show()
{
        using std::cout;
        using std::endl;
        cout << "Company: " << company
                << " Shares: " << shares << endl
                << " Share price : " << share_val
                << " Total Worth: " <<total_val <<endl;
}
int main()
{
        Stock xiaomi;
        Stock meituan;
        xiaomi.acquire("xiaomi",100,20);
        meituan.acquire("meituan",1500,100);
        xiaomi.show();
        meituan.show();
}

执行结果

所创建的每个新对象都有自己的存储空间,用于存储其内部变量和类成员;但同一个类的所有对象共享同一组类方法,也就是每种方法只有一个副本。

类的构造函数和析构函数

类的构造函数相当于类的初始化函数,因为我们之前说了,类中的私有数据只能通过公有函数来间接操作。我们无法像初始化一个int类型的值一样初始化类,例如

int a = 100;

构造函数的作用:对类进行初始化,通过设计合适的成员函数,将对象中的数据初始化。

构造函数需要向公有函数一样,在类中声明,然后定义构造函数。但是和公有函数有几点不同,

1、构造函数没有返回值。

2、构造函数的名称和类的名称保持一致,例如Stock类的构造函数的声明就形如Stock();  定义形如Stock::Stock();

3、默认构造函数,默认构造函数没有参数,就是形如Stock();这样在定义一个对象的时候,就会调用默认的构造函数。而实际上,如果我们没有提供任何构造函数,就像上面的例子,c++将提供默认构造函数,但默认构造函数为空,形如

Stock::Stock()
{

}

4、构造函数的重载,可以创建多个同名的构造函数,只要每个函数的参数列表不同。例如可以在Stock类中声明这样的构造函数

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

然后实现这个构造函数

Stock::Stock(const char *co,int n,double pr) 
{
        std::strncpy(company,co,29);
        company[29] = '\0';
        if (n < 0) {
                std::cerr << "num of shares can't be negative."
                        << company << "shares set to 0.\n";
                shares = 0;
        }
        else
                shares = n;
        share_val = pr; 
        set_tot();
}

5、构造函数的使用

可以显示的调用,例如

Stock inter = Stock("inter",1000,15.5);

或隐式的调用

Stock inter ("inter",1000,15.5);

对于只是简单的创建一个类如 Stock inter,这就相当于Stock inter = Stock(),会调用默认的构造函数。

不能像使用其他公有方法那样使用构造函数,例如我们可以Stock::show()来调用Stock类的show方法,但是不能Stock::Stock()这样来调用构造方法,因为在创建对象之前,对象还是不存在的,因此构造函数被用来创建对象,而不能通过对象来调用。

 

析构函数则是构造函数的反方向,在对象过期时,程序自动调用一个特殊的成员函数,析构函数完成清理工作。例如在构造函数中我们有用new来分配内存,在析构函数中就应该用delete释放内存。析构函数同样没有返回值,并且没有参数,在Stock类中的析构函数的声明形如~Stock(),

我们来看一个构造函数使用的例子

头文件:

#include <iostream>
#include <cstring>
class Stock
{
        private:
                char company[30];
                int shares;
                double share_val;
                double total_val;
                void set_tot(){ total_val = shares * share_val;}

        public:
                Stock();
                ~Stock();
                Stock(const char *co,int n,double pr);
                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();    
};

源文件:

#include "lei.h"                                                                                      
Stock::Stock()                                                                                        
{                                                                                                     
        std::cout << "using defualt constructor\n";                                                   
        std:strcpy(company,"no name");                                                                
        shares = 0;                                                                                   
        share_val = 0;                                                                                
        total_val = 0;                                                                                
}   

Stock::~Stock()
{
        std::cout << "bye bye!"<<std::endl;
}
                                                                                                  
Stock::Stock(const char *co,int n,double pr)                                                          
{                                                                                                     
        std::strncpy(company,co,29);                                                                  
        company[29] = '\0';                                                                           
        if (n < 0) {                                                                                  
                std::cerr << "num of shares can't be negative."                                       
                        << company << "shares set to 0.\n";                                           
                shares = 0;                                                                           
        }                                                                                             
        else                                                                                          
                shares = n;                                                                           
        share_val = pr;                                                                               
        set_tot();                                                                                    
}                                                                                                     
void Stock::acquire(const char *co,int n,double pr)                                                   
{                                                                                                     
        std::strncpy(company,co,29);                                                                  
        company[29] = '\0';                                                                           
        if (n < 0) {                                                                                  
                std::cerr << "num of shares can't be negative."                                       
                        << company << "shares set to 0.\n";                                           
                shares = 0;                                                                           
        }                                                                                             
        else                                                                                          
                shares = n;                                                                           
        share_val = pr;                                                                               
        set_tot();                                                                                    
}      
void Stock::show()                                                                                    
{                                                                                                     
        using std::cout;                                                                              
        using std::endl;                                                                              
        cout << "Company: " << company                                                                
                << " Shares: " << shares << endl                                                      
                << " Share price : " << share_val                                                     
                << " Total Worth: " <<total_val <<endl;                                               
}
int main()
{
        Stock xiaomi = Stock();
        Stock meituan("meituan",1000,12);
        xiaomi.show();
        meituan.show();
}
           

执行结果:xiaomi对象执行了默认构造函数,meituan对象执行了我们重载的构造函数

 

this指针

在 C++ 中,每一个对象都能通过 this 指针来访问自己的地址this 指针是所有成员函数的隐含参数。因此,在成员函数内部,它可以用来指向调用对象。常用的场景是在成员函数内部,将this作为参数传递出去。看一个简单的例子

#include <iostream>
using namespace std;

class Box{
        public:
                Box(){;}
                ~Box(){;}
                Box* get_address()   //得到this的地址
                {
                        return this;
                }
};

int main(){

        Box box1;
        Box box2;
        // Box* 定义指针p接受对象box的get_address()成员函数的返回值,并打印

        Box* p = box1.get_address();  
        cout << "box1 this addr: "<< p << endl;
        cout << "box1 addr: "<< &box1 << endl;

        p = box2.get_address();

        cout << "box2 this addr: "<< p << endl;
        cout << "box2 addr: "<< &box2 << endl;
        return 0;
}

执行结果

从执行结果来看,返回this值正是当前对象的地址。this的作用正是基于此:对象内部获得对象的地址。

我们再换一个角度来看this问题,对象内部的成员函数内部是怎么知道当前对象也就是this的地址呢?实际上,当我们调用一个成员函数时,会用请求该函数的对象地址初始化 this。

例如,上面程序中的box1.get_address();实际上是

box1.get_address(&box1);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值