《C++ prime plus》第十章:对象和类

10.1过程性编程和面向对象编程

面向对象编程特性:抽象;封装和数据隐藏;多态;继承;代码的可重用性。类:既有数据又有函数的复合类型。

采用过程性编程方法时,首先要考虑遵守的步骤,然后考虑如何表示这些数据。

面向对象编程,首先考虑数据——不仅要考虑如何表示数据,还要考虑如何使用数据。

采用OOP方法时,首先从用户角度考虑对象——描述对象所需的数据以及描述用户与数据交互所需的操作。完成对接口的描述后,需要确定如何实现接口和数据存储。最后,使用新的设计方案创建程序。

10.2抽象和类

将问题的本质特征抽象出来,并根据特征描述解决方案。

类是一种将抽象转换成用户定义类型的C++工具,它将数据表示和操纵数据的方法组合成一个整洁的包。

类规范由两个部分组成:

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

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

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

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

stock00.h
#ifndef STOCK00_H_
#define STOCK00_H_

#include <string>

using namespace std;

class Stock//class declaration
{
private: //私有成员
	string company;
	long shares;
	double share_val;
	double total_val;
	void set_tot() { total_val = shares * share_val; }
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();
};//note semicolon at the end

#endif

在C++中,private 和 public 是访问修饰符,它们控制类的成员(变量和函数)的访问权限。它们的作用是封装类的实现细节,使得类的使用者只能通过类提供的方式访问类的成员,从而提高代码的安全性和可维护性。

private

作用:将成员变量和成员函数设置为私有(private),这意味着它们只能在类的内部访问。类的外部代码(包括继承的子类)不能直接访问这些成员。

目的:保护类的内部数据,防止外部代码直接修改这些数据,从而避免潜在的错误和不一致性。

使用场景:通常用于存储类的内部状态,这些状态不应该被外部代码直接访问或修改。

public

作用:将成员变量和成员函数设置为公有(public),这意味着它们可以被类的外部代码访问。类的使用者可以通过这些公有成员与类的实例进行交互。

目的:提供一种方式,让外部代码可以安全地与类的实例交互,同时隐藏实现细节。

使用场景:通常用于定义类的接口,这些接口允许外部代码以受控的方式访问和修改类的内部状态。

在C++中,访问 private 成员变量或成员函数通常有以下几种方法:

通过公有成员函数:

最常见的方式是通过类提供的公有成员函数来访问和修改私有成员。这些公有函数可以提供对私有成员的受控访问。

通过友元函数:

你可以将一个函数声明为类的友元(friend),这样它就可以访问类的私有成员,即使它不是类的成员函数。

通过继承(不推荐):

如果一个类继承自另一个类,它可以访问基类的 protected 成员,但不是 private 成员。然而,使用继承来访问私有成员并不是一个好的设计,因为它破坏了封装性。

数据通常放在私有部分,组成类接口的成员函数放在公有部分;否则,就无法从程序中调用这种函数。

不必在类的声明中使用关键字private,因为这是类对象的默认访问控制。

C++程序员通常使用类来实现类描述,而把结构限制为只表示纯粹的数据对象。

定义类成员函数

成员函数定义与常规函数定义非常相似,它们有函数头和函数体,也可以有返回类型和参数。还有两个特殊特征:

定义成员函数时,使用作用域解析运算符(::)来标识函数所属的类;

类方法可以访问类的private组件。

stock00.cpp
#include <iostream>
#include "stock00.h"

using namespace std;

void Stock::acquire(const string& co, long n, double pr)
{
	company = co;// 设置公司名称
	if (n < 0)
	{
		cout << "Number of shares can't be negative; " << company << " shares set to be 0." << endl;
		shares = 0;// 如果股份数为负,则设置为0
	}
	else
		shares = n;// 否则设置股份数

	share_val = pr;// 设置每股价格

	set_tot();// 更新总价值
}

void Stock::buy(long num, double price)
{
	if (num < 0)
	{
		cout << "Number of shares can't be negative, Transaction is aborted." << endl;
	}
	else
	{ 
		shares += num;// 增加股份数
		share_val = price;// 更新每股价格
		set_tot();// 更新总价值
	}
}

void Stock::sell(long num, double price)
{
	if (num < 0)
		cout << "Number of shares can't be negative, Transaction is aborted." << endl;
	else if (num > shares)
		cout << "You can't sell more than you have! Transaction is aborted." << endl;
	else
	{
		shares -= num;// 减少股份数
		share_val = price;
		set_tot();
	}
}

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

void Stock::show()
{
	cout << "Company: " << company << endl;
	cout << "Shares: " << shares << endl;
	cout << "Share price: " << share_val << endl;
	cout << "Total worth: " << total_val << endl;
}

类里面的其他成员函数不必使用作用域解析运算符,就可以使用成员函数,因为它们从属一个类。

使用类

usestock00.cpp
#include <iostream>
#include "stock00.h"

using namespace std;

int main(void)
{
	Stock fluffy_the_cat;// 创建 Stock 对象 fluffy_the_cat
	fluffy_the_cat.acquire("NanoSmart", 20, 12.50);
	fluffy_the_cat.show();

	fluffy_the_cat.buy(15, 18.125);
	fluffy_the_cat.show();

	fluffy_the_cat.sell(400, 20.00);
	fluffy_the_cat.show();

	fluffy_the_cat.buy(300000, 40.125);
	fluffy_the_cat.show();

	fluffy_the_cat.sell(300000, 0.125);
	fluffy_the_cat.show();

	return 0;
}

要使用新类型,最关键的是要了解成员函数的功能,而不必考虑其实现的细节。

客户/服务器模型:

客户是使用类的程序。类声明(包括类方法)构成了服务器,它是程序可以使用的资源。客户只能通过以公有方式定义的接口使用服务器,这意味着客户唯一的责任是了解该接口。服务器的责任是确保服务器根据该接口可靠并准确地执行。

  • 10
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值