OPP特性:
抽象
封装和数据隐藏
多态
继承
代码的可重用性
过程性和面向对象的编程
从用户的角度考虑对象
抽象和类
基本类型完成的工作:
- 决定数据对象需要的内存单元
- 决定如何解释内存中的位
- 决定可使用数据对象执行的操作或方法
c++ 中的类
类规范
- 类声明:以数据成员的方式描述数据部分,以成员函数(方法)的方式描述公有接口。
- 类方法定义:描述如何实现类成员的函数
#include <iostream>
#include <cstring>
class Stock // class declaration
{
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 per);
void buy (int num, double price);
void sell (int num, double price);
void update(double price);
void show();
}; // semicolon
类内部包括成员和方法
只能通过公有函数来访问对象的私有成员。例如要修改Stock类的shares成员只能通过Stock的成员函数。
创建类成员函数
成员函数包括函数头和函数体,返回类型和参数,和两个特殊特征:
- 定义成员函数时,使用作用域解析操作符(::)来标识函数所属的类。
- 类方法可以访问类的private组件
update是Stock类的成员,同时可以定义另外一个类的成员函数。例如
void Buffoon::update()
方法可以访问类的私有成员。可以在show()中使用
cout << "Company: " << company << endl;
其中company是Stock类的私有成员。
void Stock::acquire(const char *co, int n, double pr)
{
std::strncpy(company, co, 29);
company[29] = '\0';
if (n < 0)
{
std::cerr << "Number of shares can't be negative"
<< company << "Shares set to 0.\n";
shares = 0;
}
else
shares = n;
share_val = pr;
set_tot();
}
void Stock::buy(int num, double price)
{
if (num < 0)
{
std::cerr << "Number of shares purchased can't be negative"
<< "Transaction is aborted.\n";
}
else
{
shares += num;
share_val = price;
set_tot();
}
}
void Stock::sell(int num, double price)
{
using std::cerr;
if (num < 0)
{
cerr << "Number of shares sold can't be negative."
<< "Transaction is aborted.\n";
}
else if (num > shares)
{
cerr << "Yon can't sell more than you have!"
<< "Transaction is aborted.\n";
}
else
{
shares -= num;
share_val = price;
set_tot();
}
}
void Stock::update(double price)
{
share_val = price;
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;
}
成员函数说明
acquire() 表示首次购买, buy 和sell表示购买和出售
cerr用于错误信息
内联方式
内联函数要求在每个使用他的文件中都要对其进行定义。
方法使用哪个对象
调用成员函数式,他将使用调用他的对象的数据成员
例如kate.show(), 相当于把show内部的shares 解释为 kate.shares
使用类
下面是完整代码
#include <iostream>
#include <cstring>
class Stock // class declaration
{
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 per); // 方法
void buy(int num, double price);
void sell(int num, double price);
void update(double price);
void show();
}; // semicolon
void Stock::acquire(const char *co, int n, double pr)
{
std::strncpy(company, co, 29);
company[29] = '\0';
if (n < 0)
{
std::cerr << "Number of shares can't be negative"
<< company << "Shares set to 0.\n";
shares = 0;
}
else
shares = n;
share_val = pr;
set_tot();
}
void Stock::buy(int num, double price)
{
if (num < 0)
{
std::cerr << "Number of shares purchased can't be negative"
<< "Transaction is aborted.\n";
}
else
{
shares += num;
share_val = price;
set_tot();
}
}
void Stock::sell(int num, double price)
{
using std::cerr;
if (num < 0)
{
cerr << "Number of shares sold can't be negative."
<< "Transaction is aborted.\n";
}
else if (num > shares)
{
cerr << "Yon can't sell more than you have!"
<< "Transaction is aborted.\n";
}
else
{
shares -= num;
share_val = price;
set_tot();
}
}
void Stock::update(double price)
{
share_val = price;
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()
{
using std::cout;
using std::ios_base;
Stock stock1;
stock1.acquire("NanoSmart", 20, 12.50);
cout.setf(ios_base::fixed);
cout.precision(2);
cout.setf(ios_base::showpoint);
stock1.show();
stock1.buy(15, 18.25);
stock1.show();
stock1.sell(400, 20.00);
stock1.show();
return 0;
}
类的构造函数和析构函数
C++的目标之一是使用类对象就像使用标准类型一样。例如想int一样初始化对象。如下
int year = 2001; // valid initialization
struct thing
{
char * pn;
int m;
}
thing amabob = { "wodget", -23} //valid initialization
Stock hot = {"Sukie's Autos, Inv.", 200, 50.2} // compile error
不能初始化Stock对象是因为,数据部分的访问转态是私有的。只能通过成员函数来访问数据成员。
类构造函数:专门用于构造新对象。
构造函数没有声明类型。
声明和定义构造函数
采用默认参数来完成。如下是函数原型
Stock(const char *co, int n = 0, double pr = 0.0);
下面是一种可能的定义
Stock::Stock(const char * co, int n, double pr)
{
std::strncpy(company, co, 29);
company[29] = '\0';
if (n < 0)
{
std::err << "Number of shares can't be negative;"
<< company << " shares set to 0. \n";
shares = 0;
}
else
shares = n;
share_val = pr;
set_tot();
}
使用构造函数
显示调用
Stock food = Stock("World Cabbage", 250, 1.25);
隐式调用
Stock garment ("Furry Mason", 50, 2.5);
构造函数和new一起使用的方法
Stock *pstock = new Stock ("Electroshock Games", 18, 19.0);
Stock对象没有名称,属于对象指针。
无法使用对象来调用构造函数。
默认构造函数
例如上面的完整代码中的
Stock stock1;
等价于 int x;
只有在没有定义任何构造函数的时候,才能编译。否则会报错。
析构函数
析构函数完成清理工作。
析构函数在类名前加~;
~Stock();
析构函数不执行任何操作的函数;
改进Stock类
C++的通常做法,将程序组织成独立的文件。
我们将类声明放在stock1.h中
类方法被放在stock1.cpp中
头文件stock1.h
#ifndef STOCK1_H_
#define STOCK1_H_
class Stock // class declaration
{
private:
char company[30]; // 成员
int shares;
double share_val;
double total_val;
void set_tot() { total_val = shares * share_val; }
public:
Stock();
Stock(const char *co, int n = 0, double pr = 0.0);
~Stock();
void buy(int num, double price);
void sell(int num, double price);
void update(double price);
void show();
};
#endif
方法文件stock1.cpp
#include <iostream>
#include <cstring>
#include "stock1.h"
Stock::Stock()
{
std::cout << "Default constructor called\n";
std::strcpy(company, "no name");
shares = 0;
share_val = 0.0;
total_val = 0.0;
}
Stock::Stock(const char *co, int n, double pr)
{
std::cout << "Constructor using " << co << " called\n";
std::strncpy(company, co, 29);
company[29] = '\0';
if (n < 0)
{
std::cerr << "Number of shares can't be negative"
<< company << "Shares set to 0.\n";
shares = 0;
}
else
shares = n;
share_val = pr;
set_tot();
}
// class destructor
Stock::~Stock()
{
std::cout << "Bye, " << company << "!\n";
}
// other methods
void Stock::buy(int num, double price)
{
if (num < 0)
{
std::cerr << "Number of shares purchased can't be negative"
<< "Transaction is aborted.\n";
}
else
{
shares += num;
share_val = price;
set_tot();
}
}
void Stock::sell(int num, double price)
{
using std::cerr;
if (num < 0)
{
cerr << "Number of shares sold can't be negative."
<< "Transaction is aborted.\n";
}
else if (num > shares)
{
cerr << "Yon can't sell more than you have!"
<< "Transaction is aborted.\n";
}
else
{
shares -= num;
share_val = price;
set_tot();
}
}
void Stock::update(double price)
{
share_val = price;
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;
}
使用类文件
#include <iostream>
#include "stock1.h"
int main()
{
using std::cout;
using std::ios_base;
cout.precision(2);
cout.setf(ios_base::fixed, ios_base::floatfield);
cout.setf(ios_base::showpoint);
cout << "Using constructors to create new objects\n";
Stock stock1("NanoSmart", 12, 20.0);
stock1.show();
Stock stock2 = Stock("Boffo Objects", 2, 2.0);
stock2.show();
cout << "Assigning stock1 to stock2: \n";
stock2 = stock1;
cout << "Listing stock1 and stock2: \n";
stock1.show();
stock2.show();
cout << "Using a constructor to reset an object \n";
stock1 = Stock("Nifty foods", 10, 50.0);
cout << "Revised stock1: \n";
stock1.show();
cout << "Done\n";
return 0;
}
const成员函数
只要类方法没有修改调用对象,后面都应加上const,例如
void show() const;
this 指针
比较两个类对象的值,返回其中较大的一个。
const Stock & topval (const Stock & s ) const;
两个const分别表示两个调用对象的值不变
函数调用如下
top = stock1.topval(stock2);
const Stock & Stock::topval (const Stock & s) const
{
if (s.total_val > total_val)
return s;
else
return ???;
}
第二种情况的返回值没有称呼。
解决方法: this指针。
this指针指向用来调用成员函数的对象。
const Stock & Stock::topval (const Stock & s) const
{
if (s.total_val > total_val)
return s;
else
return *this;
}
头文件stock2.h
#ifndef STOCK2_H_
#define STOCK2_H_
class Stock // class declaration
{
private:
char company[30]; // 成员
int shares;
double share_val;
double total_val;
void set_tot() { total_val = shares * share_val; }
public:
Stock();
Stock(const char *co, int n = 0, double pr = 0.0);
~Stock(){};
void buy(int num, double price);
void sell(int num, double price);
void update(double price);
void show() const;
const Stock & topval (const Stock & s) const;
};
#endif
类方法stock2.cpp
#include <iostream>
#include <cstring>
#include "stock2.h"
Stock::Stock()
{
std::cout << "Default constructor called\n";
std::strcpy(company, "no name");
shares = 0;
share_val = 0.0;
total_val = 0.0;
}
Stock::Stock(const char *co, int n, double pr)
{
std::cout << "Constructor using " << co << " called\n";
std::strncpy(company, co, 29);
company[29] = '\0';
if (n < 0)
{
std::cerr << "Number of shares can't be negative"
<< company << "Shares set to 0.\n";
shares = 0;
}
else
shares = n;
share_val = pr;
set_tot();
}
// class destructor
//Stock::~Stock()
//{
// std::cout << "Bye, " << company << "!\n";
//}
// other methods
void Stock::buy(int num, double price)
{
if (num < 0)
{
std::cerr << "Number of shares purchased can't be negative"
<< "Transaction is aborted.\n";
}
else
{
shares += num;
share_val = price;
set_tot();
}
}
void Stock::sell(int num, double price)
{
using std::cerr;
if (num < 0)
{
cerr << "Number of shares sold can't be negative."
<< "Transaction is aborted.\n";
}
else if (num > shares)
{
cerr << "Yon can't sell more than you have!"
<< "Transaction is aborted.\n";
}
else
{
shares -= num;
share_val = price;
set_tot();
}
}
void Stock::update(double price)
{
share_val = price;
set_tot();
}
void Stock::show() const
{
using std::cout;
using std::endl;
cout << "Company: " << company
<< " Shares: " << shares << endl
<< " Share Price: $" << share_val
<< " Total worth: $" << total_val << endl;
}
const Stock &Stock::topval(const Stock &s) const
{
if (s.total_val > total_val)
return s;
else
return *this;
}
对象数组
声明对象数组的方法和声明标准类型数组相同,例如
Stock mystuff [4]
初始化对象数组,这个类一定要有默认构造函数
使用类函数
#include <iostream>
#include "stock2.h"
const int STKS = 4;
int main()
{
using std::cout;
using std::ios_base;
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.precision(2);
cout.setf(ios_base::fixed, ios_base::floatfield);
cout.setf(ios_base::showpoint);
cout << "Stock holdings: \n";
int st;
for (st = 0; st < STKS; st++)
stocks[st].show();
Stock top = stocks[0];
for (st = 1; st < STKS; st++)
top = top.topval(stocks[st]);
cout << "\nMost valuable holding: \n";
top.show();
return 0;
}
接口和实现小结
类作用域
类成员只在所属中是已知的,所以不同的类可以有相同的名称。并且不能从外部访问
类的声明中不能存储对象
但是可以用关键词static
static const int Len = 30;
抽象数据类型
栈
头文件stack.h
#ifndef STACK_H_
#define STACK_H_
typedef unsigned long Item;
class Stack
{
private:
enum
{
MAX = 10
};
Item items[MAX];
int top;
public:
Stack();
bool isempty() const;
bool isfull() const;
bool push(const Item &item);
bool pop(Item &item);
};
#endif
类方法文件 stack.cpp
#include <iostream>
#include "stack.h"
Stack::Stack()
{
top = 0;
}
bool Stack::isempty() const
{
return top == 0;
}
bool Stack::isfull() const
{
return top == MAX;
}
bool Stack::push(const Item &item)
{
if (top < MAX)
{
items[top++] = item;
return true;
}
else
return false;
}
bool Stack::pop(Item &item)
{
if (top > 0)
{
item = items[--top];
return true;
}
else
return false;
}
使用类文件
#include <iostream>
#include <cctype>
#include "stack.h"
int main()
{
using namespace std;
Stack st;
char ch;
unsigned long po;
cout << "Please enter A to add a purchase order, \n"
<< "P to process a PO, or Q to quit.\n";
while (cin >> ch && toupper(ch) != 'Q')
{
while (cin.get() != '\n')
continue;
if (!isalpha(ch))
{
cout << '\a';
continue;
}
switch (ch)
{
case 'A':
case 'a':
cout << "Enter a PO number to add: ";
cin >> po;
if (st.isfull())
cout << "stack already full\n";
else
st.push(po);
break;
case 'P':
case 'p':
if (st.isempty())
cout << "stack already empty\n";
else
{
st.pop(po);
cout << "PO #" << po << " popped\n";
}
break;
}
cout << "Please enter A to add a purchase order, \n"
<< "P to process a PO, or Q to quit. \n";
}
cout << "Bye\n";
return 0;
}
标签:const,val,int,double,void,第十章,C++,primer,Stock
From: https://blog.csdn.net/weixin_48442204/article/details/141948247