C++中的类

类是一种将抽象转换为用户定义类型的C++工具,他将数据表示和操纵数据的方法组合成一个整洁的包。
比如有一个股票的类,可以把他的价格,持有人,数量等等,我们可以将股票简化,将操作限制为获得股票、增持、卖出股票、更新股票价格、显示关于股票的信息。此外我们还需要存储一些信息

  • 公司名称
  • 所持股票数量
  • 每股的价格
  • 股票总值
    这样我们的类大致分为两部分。
  • 类声明:以数据成员的方式描述数据部分,以成员函数(被称为方法)的方式描述共有接口
  • 类方法定义:描述如何实现类成员函数

接口

接口是一个共享框架。供两个系统交互时使用。比如用户在文档输入一串文字需要用到键盘,需要移动鼠标,计算机接口将用户操作转换为存储在计算机中的具体信息。
对于类,接口是用户调用类的程序,交互系统就是类对象,而接口是编写类的人提供的方法,接口让程序员能够编写与类对象交互的代码,从而让程序能够使用类对象,比如要计算string对象中的字符,可以用方法size,也是接口,如果要使用类,必须了解其公共接口,如果要编写类,必须创建其公共接口。

通常C++程序员把接口(类定义)放在头文件当中,并将实现方法(类方法)放在程序源代码当中。

class Stock
{
};

Stock是这个新类的类型名,该声明可以让我们能够声明Stock类型的变量、对象或者实例。每个对象都代表一支股票。
Stock Bill;
Stock white;//表示Bill和white持有某公司股票
我这里直接把书上的例子搬过来。

#include<iostream>
using namespace std;
class Stock
{
private:

	string company;
	long share;
	double share_val;
	double total_val;
	void set_tot() { total_val = share_val * share; }
public:
	void acquire(const string& co, long n, double pr);
	void buy(long num, double price);
	void sell(long num, double price);
	void update(double price);
	void show();
};
  • company存储了公司的名称
  • share存储了持有的股票数量
  • share_val存储了每股股票的价格
  • total存储了股票总价格
    要执行的操作以成员函数形式出现。成员函数可以就地定义,也可以只写声明,在源代码处定义。类的特性是把数据和方法组成一个单元,可以更方便地使用类。

访问控制

private 意为私有的,私生的 成员,只能被本类的成员函数所引用,类外部不能调用(友元类可以,这个以后说明)
public 意为共有的,公开的,公用的 成员,既可以被本类中的成员函数引用,也可以被类的作用域的其他函数所引用,即从类的外部是可以调用的;
protected:意为受保护的成员,不能被类外访问,这点类似private,但是可以被派生类的成员函数访问,有关派生类的说明,以后会讲解。
比如share数据,我们如果要修改它,只能通过Stock的成员函数修改,因为公有成员函数是程序和对象的私有成员之间的桥梁,提供了对象和程序之间的接口。
一般情况下如果不希望外界访问到类中的成员变量,可以设为private,但是必须提供公开的成员函数,如果都设为private,外界函数无法调用,那么我们的数据是无意义的。我想知道知道Bill持有股票的信息,因此在公开的成员函数有show这个成员函数。当然也可以为某些特殊的成员变量设置private但不提供修改接口,这类变量不需要外界使用,只供类使用。还可以把成员函数私有,仅在辅助类内成员函数调用,不对外公开。
这里要说明的是类默认权限是private

实现类成员函数

成员函数特征:

  • 定义成员函数 使用::作用域解析运算符标明所属类
  • 类方法可以访问private成员
    比如我要访问上面类中的update函数
    void Stock::update(double price)
    这种表示说明update方法是属于Stock类。其他成员函数在使用update函数时,不需要作用域符号,因为他们都属于一个类的作用域中
    关于第二个特征:
    可以在show()中这样写
    std::cout<<“company = “<<company; //其他私有变量也可以使用
    其中的数据成员都是私有,如果用非成员函数访问,编译器不会允许。然后我们下面就去实现类方法,把他写在一个头文件当中 stock.h
#pragma once
#include<string>
class Stock
{
private:

	std::string company;
	long share;
	double share_val;
	double total_val;
	void set_tot() { total_val = share_val * share; }
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();
};
#include<iostream>
#include"stcok.h"
void Stock::acquire(const std::string& co, long n, double pr)
{
	company = co;
	if (n<0)
	{
		std::cout << "Number of shares can't be negative;"
			<< company  << "share set to 0.\n";
		share = 0;
	}
	else
	{
		share = n;
		share_val = pr;
		set_tot();
	}
}
void Stock::buy(long num, double price)
{
	if (num < 0)
	{
		std::cout << "Number of shares purchased can't be negative."
			<< "Transcation is aborted.\n";
	}
	else
	{
		share+= num;
		share_val = price;
		set_tot();
	}
}
void Stock::sell(long num, double price)
{
	using std::cout;
	if (num<0)
	{
		cout << "Number if shares sold can't be negative. "
			<< "Transcation is aborted.\n";
	}
	else
	{
		share -= num;
		share_val = price;
		set_tot();
	}
}
void Stock::update(double price)
{
	share_val = price;
	set_tot();
}
void Stock::show()
{
	std::cout << "Company: " << company
		<< "Share: " << share << '\n'
		<< "share price: $" << share_val
		<< "Total Worth: $" << total_val << '\n';
}
  • acpuire()函数管理对某个公司股票的首次购买
  • buy() sell()管理增加和减少 股票肯定不能负数 公有函数有利于对私有数据的维护和防护
    四个成员函数都修改了total的值 作为辅助函数辅助公有函数,节省了代码量,且如果要修改,工作量也不大。
    这里需要说明的是定义位于类声明中的函数会被自动转为内联函数。内联函数就是编译器在编译时,把调用函数替换成了函数代码,减少函数调用开销,适合一些短小的函数。如果不愿意也可以在类声明之外定义内联函数,需要在定义加入inline 如
class Stock
{
private:
...
void hook();
public:
...
}
inline void Stock::hook()
{
...
}

内联函数要求要求在使用他的文件中都有定义,这样内联函数的定义一般在头文件当中

对象的创建

上面我们都没有介绍了类的内部结构,那么如何创建对象。

  • 声明类变量
    Stock White,Bill;
    这样就可以利用对象调用成员函数White.show() Bill.show() 在调用成员函数时,如果函数内部调用了数据成员,那么这个数据成员对应调用他的对象。我们之前学习结构体的时候,我们每个实例化对象都有自己的内存存储空间,类也是一样的,用来存储内部变量和类成员,但是同一个类用的都是同一组类方法,他们将执行同一个代码块,只是代码用到的数据不同。

image.png

使用类

C++的目标是使得类和基本类型尽可能相同,我们类的声明和定义都已经编写完成,下面我们通过文件来使用这些接口测试一下:

image.png

这里还需要说明一下C++的文件结构,以及这里我们使用到了之前在C语言预编译处理中说到的内容
头文件经常包含的内容

  • 函数原型
  • 符号常量(#define 和 const)
  • 结构声明
  • 类声明
  • 模板声明
  • 内联函数
    如果你遇到了

image.png

这种情况说明了你的文件之间出现了重定义的问题。简单来说就是有一个头文件被另一个头文件包含,另一个文件又包含了这个头文件,一个头文件被包含了两次,也就是头文件重复包含。而#ifndef 如果编译器没有发现_STOCK_H则执行ifndef中间的代码,下一次再遇到就不会在包含这块代码。就避免了重定义的问题。

网站标题:CV鼻祖洋芋

原创文章,作者:locus,如若转载,请注明出处:https://blog.cvpotato.cn/forward-code/c/196/

本博客所发布的内容,部分为原创文章,转载注明来源,网络转载文章如有侵权请联系站长!

(0)
上一篇 6天前
下一篇 6天前

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注