IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 2021-8-8 C++Primer Plus 对象和类 -> 正文阅读

[C++知识库]2021-8-8 C++Primer Plus 对象和类

实例导入

stock10.h:

//stcok10.h
#ifndef STOCK10_H_
#define STOCK10_H_
#include<string>

class Stock
{
private:
	std::string m_company;
	long m_shares;
	double m_share_val;
	double m_total_val;
	void set_tot() { m_total_val = m_shares * m_share_val; }
public:
	Stock();
	Stock(const std::string& company, long shares = 0, double share_val = 0.0);
	~Stock();
	void buy(long num, double price);
	void sell(long num, double price);
	void update(double prices);
	void show() const;
	const Stock& topval(const Stock& s) const;
};

#endif

stokc10.cpp

//stock10.cpp
#include<iostream>
#include"stock10.h"

//default constructor
Stock::Stock()
{
	m_company = "no name";
	m_shares = 0;
	m_share_val = 0.0;
	m_total_val = 0.0;
}

//constructor
Stock::Stock(const std::string& company, long shares, double share_val)
{
	m_company = company;

	if (shares < 0)
	{
		std::cout << "Number of shares can't be negative; " << m_company << "shares set to 0" << std::endl;
		m_shares = 0;
	}
	else
		m_shares = shares;

	m_share_val = share_val;
	set_tot();
}

//destructor
Stock::~Stock()
{
	std::cout << "Bye, " << m_company << "!" << std::endl;
}

//buy shares
void Stock::buy(long num, double price)
{
	if (num < 0)
	{
		std::cout << "Number of shares can't be negative. Transaction is aborted." << std::endl;
	}
	else
	{
		m_shares += num;
		m_share_val = price;
		set_tot();
	}
}

//sell shares
void Stock::sell(long num, double price)
{
	if (num < 0)
	{
		std::cout << "Number of shares can't be negative. Transaction is aborted." << std::endl;
	}
	else if (num > m_shares)
	{
		std::cout << "You don't have so many shares. Transaction is aborted." << std::endl;
	}
	else
	{
		m_shares -= num;
		m_share_val = price;
		set_tot();
	}
}

//update shares
void Stock::update(double prices)
{
	m_share_val = prices;
	set_tot();
}

//show shares
void Stock::show() const
{
	using std::cout;
	using std::ios_base;
	using std::endl;
	ios_base::fmtflags orig = cout.setf(ios_base::fixed, ios_base::floatfield);
	std::streamsize prec = cout.precision(3);

	cout.width(16);
	cout << "   Company:  " << m_company << endl;
	cout.width(15);
	cout << "Shares:  " << m_shares;
	cout.width(15);
	cout << "   Share Price: $" << m_share_val << endl;
	cout.precision(2);
	cout << "      Total Worth: $" << m_total_val << endl;
	cout.setf(orig, ios_base::floatfield);
	cout.precision(prec);
	cout << endl;
}

const Stock& Stock::topval(const Stock& s) const
{
	if (s.m_total_val > m_total_val)
		return s;
	else
		return *this;
}

源.cpp

//usestock10.cpp…using the Stock class
#include<iostream>
#include"stock10.h"
const int STKS = 4;

int main()
{
	using namespace std;

     Stock food1 = Stock("First World Cabbage", 250, 1.25);
	 food1.show();
	 Stock food2 ("Second World Cabbage", 250, 1.25);
	 food2.show();
	 food1=Stock("Third World Cabbage", 250, 1.25);
	 food1.show();
	 cout << endl;

	Stock stocks[STKS]{
		Stock("NanoSmart",12,20.0),
		Stock("Boffo Objects",200,2.0),
		Stock("Monolithic Obelisks",130,3.25),
		Stock("Fleep Enterprises",60,6.5)
	};
		
	cout << "Stock holding:\n";
	for (int i = 0; i < STKS; i++)
		stocks[i].show();
	const Stock* top = &stocks[0];
	for (int i = 1; i < STKS; i++)
		top = &top->topval(stocks[i]);
	cout << endl;
	cout << "Most valuable shares: " << endl;
	top->show();

	system("pause");
	return 0;
}

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

2.通俗约定类名首字母会大写;

类成员前有前缀m_,且一般放在私有部分中,使得数据只能被授权的函数访问;

类方法一般放在共有部分中,且在定义时需要加上类作用域如void Stock::update(double prices);

定义位于类声明中的函数都将自动成为内联函数(可省略inline),因此Stock::set_tot()是一个内联函数,且为了确保内联定义对多文件程序中的所有文件都可用需将内联定义放在类的头文件中,这等同于原型替换方法定义,然后在类声明的后面将定义改写成内联函数;

类class和结构struct具有类似的性质,区别是class默认访问类型为private而struct默认访问类型为public。

3.?? 修改实现:

ios_base::fmtflags orig = cout.setf(ios_base::fixed, ios_base::floatfield);
std::streamsize prec = cout.precision(3);

orig将储存所有格式标记,并可使用重置语句cout.setf(orig, ios_base::floatfield);将floatfield重置,同理prec储存了输出小数的位数,效果类似。

4.构造函数

(1)构造函数的名称与类名相同,且没有声明类型,一般用于类成员初始化;

(2)显示调用构造函数:Stock food = Stock(“World Cabbage”,250,1.25);

这条初始化语句将创建一个Stock临时对象(也可能不会),并将其初始化为参数提供的值,再赋给Stock对象food;

(3)隐式调用构造函数:Stock food (“World Cabbage”,250,1.25);

这条语句将直接调用构造函数给创建的Stock对象food赋值;

(4)搭配new使用构造函数:Stock *food = new Stock(“World Cabbage”,250,1.25);

这条语句将创建一个Stock对象,并将其初始化为参数提供的值,再将该对象的地址赋给food指针,在这种情况下对象没有名称,但是可以使用food指针管理该对象;

(5)无法使用对象来调用构造函数,因为在构造函数使用前对象不存在,构造函数是用来创建对象的,不可通过对象调用;

(6)为类定义了构造函数后,编译器就不会为程序提供默认构造函数,程序员需要自己提供默认构造函数来为所有的成员提供隐式初始值;

(7)调用默认构造函数时,不用使用圆括号,如Stock first;

5.析构函数

(1)析构函数的名称为~类名,如Stock类的析构函数为~Stock(),且析构函数可以没有返回值和声明类型,不接受参数;

(2)如果创建的是静态存储对象,则其析构函数将在程序运行结束时自动调用;

如果创建的是自动存储类对象,则其析构函数将在程序执行完代码块时自动被调用;

如果对象时通过new创建的,则它将驻留在栈内存或自由存储区中,当使用delete释放内存是,其析构函数会被自动调用,当然这个析构函数也可包含delete,在程序结束前释放其内存;

(3)有时调用构造函数赋值会创建一个临时对象:

?food1=Stock("Third World Cabbage", 250, 1.25);

这个临时对象在赋值给food1后会被丢,编译器会给它使用析构函数;

(4)最后创建的对象会被最先删除,最先创建的对象会被最后删除;

(5)可以将列表初始化语句用于类,只要提供与某个构造函数的参数列表匹配的内容,并用大括号括起,如:Stock food2 {"Second World Cabbage", 250, 1.25};且如果使用默认构造函数也需要大括号,即使内容为空;

6.const

C++将const关键字放在类方法的括号后面,如show()声明:void show ()const;

同时show()定义为:void Stock::show() const

可以保证不会修改访问对象的数据。

7.this指针

const Stock& Stock::topval(const Stock& s) const
{
	if (s.m_total_val > m_total_val)
		return s;
	else
		return *this;
}

(1)其中括号中的const保证不会修改显示地访问的对象s,括号后面的const表明该函数不会修改被隐式地访问的对象;

(2)topval() 中的m_total_val其实是this->m_total_val的简写,this是隐式访问的对象地址,*this是隐式地访问的对象本身。

8.对象数组

(1)与指针结合,如:??? const Stock* top = &stocks[0];

(2)要创建类对象数组,则这个类必须要有默认构造函数,且未被构造函数初始化的数组元素会被默认构造函数初始化。

9.作用域为类的常量

(1)声明类只是描述了对象的形式,并没有创建对象,因此在创建对象前将没有用于存储值的空间。所以说在类声明中的语句:const int MONTHS = 12;不合理;

(2)可以使用枚举创建符号常量,如enum{MONTHS = 12};

且并不会提供枚举名;后面若在作用域为整个类的代码中出现MONTHS,会用12代替;

传统的枚举会存在一些问题,其中之一是两个类枚举定义中的枚举量冲突,为了解决这个问题C++11提供了一种新枚举,其作用域为类,如:

enum class egg {Small, Medium, Large, Jumbo};

但这种枚举不能隐式地转换为整形,如int king = egg::large将不合理,需要使用显示类型转换如:int Frodo = int(egg::Small);

也可如:enum class : short egg {Small, Medium, Large, Jumbo};

: short将底层类型制定为short。

(3)可以使用static如:static const int MONTHS = 12;

该变量将与其他静态变量存储在一起而不是存储在对象中;

10.#ifndef和endif搭配使用,如果已经define过STOCK10_H_(在编译器内部的stock10.h),该头文件将直接跳到endif;#pragma once 可以防止头文件冲突。

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-08-09 10:03:37  更:2021-08-09 10:04:43 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/9 19:54:35-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码