C++中的类

一、接口

1.举个例子,A想要去B的家里做客,当然,A不能直接穿墙或瞬移进入到B家里去访问,他必须通过某种方式或渠道才能进入到B的家里。这时候,这种方式或渠道可以称之为B的家对外的接口。
2.接口可以分为两种:公共接口(Public) 和 私有接口(private) 。公共接口可以看做是B家的窗户、大门,任何人都可以访问;私有接口则可以看做B家里的私密通道,只有他家里的成员对象或者通过他家里的私密方法才能进入和访问。

请看如下代码:

#ifndef Stock_hpp
#define Stock_hpp

#include 
#include 
#include 

/*
 *class关键字指出这些代码定义了一个类设计
 *Stock是这个类的类型名(类的名称)
 *通过这个声明,我们可以创建Stock类型的变量(也可以说是Stock的对象)
 **/
class Stock
{
private:

    std::string company;
    double share_value;
    double total_value;
    long share;
    void set_tot(){total_value = share *share_value;};

public:

    void acquire(const std::string & co ,long n, double pr);
    void buy(long num,double price);
    void sell(long num,double price);
    void update(double price);
    void show();

};

#endif /* Stock_hpp */

简要说明:

1.class关键字指出这些代码的作用:定义了一个类设计
2.Stock是这个类的类型名(也可以理解为类名;
3.通过这个声明,我们可以创建Stock类型的变量(也可以说是Stock类型的对象)
4.private和public则分别是接口中的私有部分和公有部分

1.访问控制

关键字private和public对类成员的访问控制,我们可以通过类的对象来访问公有部分,但是访问私有成员则只能通过公有成员函数。比如,我们想修改Stock类的total_value成员,只能通过Stock的成员函数。因此公有成员函数是程序 和 对象的私有成员之间的桥梁,提供了对象和成员之间的接口。防止程序直接访问数据被称为数据隐藏 。C++还提供了第三个访问控制关键字protected类的成员可以是数据类型,也可以是函数。

2.控制对成员的访问:公有还是私有

无论类成员是数据成员还是成员函数,我们都可以在类的公有部分或者是私有部分中声明它。由于隐藏数据是OOP主要目标之一,因此数据项通常放在私有部分,组成类接口的成员函数放在公有部分。如上面的代码,我们可以把成员函数放在私有部分中,此时我们不能直接通过程序调用这些函数,但是我们可以通过公有部分中的成员函数来访问它们。

在C++中,类与结构体具有相同的特性,它们之间的唯一区别就是:结构体默认访问类型是public公有部分,类默认访问的是private私有部分。我们通常使用类来实现类描述,而结构体通常只用来表示纯粹的数据对象。

二、实现类成员函数

我们在类声明中声明成员函数的函数原型之后,还需要实现对应的函数。成员函数的定义与常规函数的定义非常相似,他们也有函数头和函数体,也有返回类型和参数。但是他们还有两个特殊的标识特征:

1.定义成员函数时,使用作用域解析运算符(::)来标识函数所属的类
2.类方法可以访问类的private组件。

如下:
void Stock :: update(double price)

1.我们定义的update( )函数是Stock类成员
2.此外,我们还可以在其它的类中也定义一个名为update( )的成员函数,例如,People( )类中的update( )函数的函数头为:
void People :: update(double peice);

也就是说,作用域解析运算符确定了方法(函数)定义对应的类的身份,函数update( )具有类作用域(class scope)Stock类的其它成员不必再使用作用域解析运算符就可以使用update( )方法,这是因为他们属于同一个类,update( )是可见的
类方法的完整名称中包括类名,Stock :: update( )是函数的限定名(qualified name);而update( )是全名的缩写,是非限定名(unqualified name ),它只能在类作用域中使用。
请看如下代码:

#include "Stock.hpp"
#include 
using namespace std;

#pragma mark --
/**函数void acquire(const std::string & co ,long n, double pr);的实现**/
void Stock::acquire(const std::string &co, long n, double pr)
{
    company =  co;
    if (n > 0)
    {
        cout << "Number of shares can’t ne negative;"
             << company
             << "Share set to Zero."
             << endl;
        share = 0;
    }
    else
    {
        share = n;
    }
    share_value = pr;
    set_tot();
}

#pragma mark --
/**函数void Stock::buy(long num, double price)的实现**/
void Stock::buy(long num, double price)
{
    if (num < 0) {
        cout << "Number of shares purchase can't be negative."
             << "Transaction is aborted ;"
             << endl;
    }
    else
    {
        share += num;
        share_value = price;
        set_tot();
    }
}

void Stock:: sell(long num, double price)
{
    if (num < 0)
    {
        cout << "Number of shares sold can't be negative."
             << "Tansaction is aborted."
             << endl;
    }
    else if(num >share)
    {
        cout << "You can't sell more than you have!"
             << "Transaction is aborted ."
             << endl;
    }
    else
    {
        share_value = price;
        set_tot();
    }
}

void Stock:: update(double price)
{
    share_value = price;
    set_tot();
}

void Stock::show()
{
    cout << "Company:" << company
         << "Shares :" << share
         << endl
         << "Share Price: $" << share_value
         << "Total Worth: $" << total_value
         << endl;

}
1.成员函数说明:

4个成员函数设置或者重新设置了total_value成员值,这个类并非将计算部分的代码编写了四次,而是让每个使用到的函数都去调用set_out( )函数。set_out( )只是实现代码的一种方式,不是公有接口的组成部分,所以在这个类中将它声明为私有成员函数(即:编写这个类的人可以使用,但编写代码使用这个类的人不能使用)。这种方式的好处在于通过函数调用,提高代码的重用率,同时在修改起来也比较容易。

2.内联函数

定义位于类声明中的函数都将自动成为内联函数,因此,如上代码,Stock :: set_tot()是一个内联函数。
类声明常将短小的成员函数作为内联函数,set_tot()符合要求。
此外,也可以在类声明之外定义成员函数,并将其成为内联函数。只需要在类实现部分中定义函数时使用inline限定符即可。
如下:

class Stock
{
private:
    ...
    void set_tot();
public:
    ...
    ...
};

inline void Stock::set_tot()
{
    total_value = share *share_value;
}

内联函数的特殊规则要求在每个使用他们的文件中都对其进行定义,确保内联定义对多文件程序中的所有文件都是可用的。。最简单的方法就是:将内联定义放在定义类的头文件中
根据改写规则:在类声明中定义方法等同于用原型替换方法定义,然后在类声明的后面讲定义改写为内联函数

3.方法使用哪个对象?

如下代码:

    Stock kate,joe;//创建两个Stock对象
    kate.show();//1.
    joe.show();//2.

第一条语句调用kate对象的show()成员,这意味着show()shares解释为 kate.shares,将share_value解释为kate.shares。同理,第二条也如此。
注意:

调用成员函数时,它将使用被用来调用它的对象的数据成员

4.使用类
#include 

#include "Stock.hpp"

using namespace std;
int main(int argc, const char * argv[]) {

    Stock class_obj;

    class_obj.acquire("GuPiao007", 20, 12.12);
    class_obj.show();

    class_obj.buy(10, 18.88);
    class_obj.show();

    class_obj.sell(400, 20.11);
    class_obj.show();

    class_obj.buy(8888, 40.123);
    class_obj.show();

    class_obj.sell(3000000, 0.111);
    class_obj.show();

    return 0;
}

输出结果:

Number of shares can’t negative;GuPiao007
Share set to Zero.
Company:GuPiao007Shares :0
Share Price: $12.12Total Worth: $0
Company:GuPiao007Shares :10
Share Price: $18.88Total Worth: $188.8
You can't sell more than you have!Transaction is aborted .
Company:GuPiao007Shares :10
Share Price: $18.88Total Worth: $188.8
Company:GuPiao007Shares :8898
Share Price: $40.123Total Worth: $357014
You can't sell more than you have!Transaction is aborted .
Company:GuPiao007Shares :8898
Share Price: $40.123Total Worth: $357014
Program ended with exit code: 0

在前面,我们定义和实现了成员函数之后,就会使用到这个类。比如,我们在main.cpp类中使用Stock类中公有部分的成员函数时,就需要先导入Stock类的头文件 。之前,我们在使用cincout方法时,就导入了它们所在类的头文件iostream。如下:

#include
#include "Stock.hpp"

当然,你会发现它们两个有所区别,一个使用< >来包括头文件名,一个使用" "来包括头文件名。它们的区别就是:前者用于导入系统所有类的头文件,而后者用于导入程序员自己创建类的头文件

说明:

1.在上面的代码中,class_obj是通过Stock类的类名创建的Stock类的对象。用一个例子来说明类与对象的关系,就是:类就好比是永辉超市集团,而对象就是我们所见到的永辉超市。当然,这个例子比喻得比不是十分恰当。
2.我们在使用Stock类并编译时,一定要确保使用它的类和Stock.cpp一起编译,并确保Stock.hpp在当前文件夹内。

5.总结
提供类声明

1.指定类设计的第一步是提供类声明,类声明和结构声明类似可以包括数据成员和结构成员。
2.声明通常分为两部分:私有部分公有部分。私有部分中声明的成员只能通过成员函数进行访问;声明在公有部分中的成员可以被使用类对象的程序直接访问。
3.一般类声明的格式如下:

class className {
private:
data member declarations
public:
member function prototypes
};

4.公有部分的内容构成了设计的抽象部分:```公有接口```。将数据封装到私有部分中可以保护数据的完整性,这被称为```数据隐藏```。
实现类成员函数

指定类设计的第二步是实现类成员函数。可以在类声明中提供完整的函数定义,而不是函数原型。但是通常的做法就是单独提供函数定义(除非函数非常小)。在这种情况下,我们需要使用作用域解析运算符来指出成员函数属于哪个类。看个例子:LOL类有个doubleKill()成员函数,这个成员函数返回int类型数据,则该成员函数的函数头如为:int LOL::doubleKill()

创建类的对象

创建一个类的对象,就是将该类进行实例化。具体的创建方法为:className classObj;,类对象通过成员运算符句点来调用类的成员函数,比如:

className classObj;
classObj.memberFunc();

你可能感兴趣的:(C++中的类)