一、过程性编程和面向对象编程(OOP)
- 过程性编程:先确定步骤,在考虑如何表示数据
- OOP:首先考虑数据,确定用户接口,再实现接口和数据存储
二、抽象和类
1. 类型
指定基本类型完成了三项工作(例如int\float)
- 决定数据对象需要的内存数量
- 决定如何解释内存中的位(long/float)
- 决定可适用数据对象执行的操作或方法
2. C++中的类
- 类声明:描述数据和接口(成员函数),通常放在头文件中
- 类定义:实现类成员函数,放在源代码文件中
//stock00.h
#ifndef STOCK00_H_
#define STOCK00_H_
#include<String>
class Stock{
private:
std::string company;//公司名称
long shares;//股票数量
double share_val;//股票每股价格
double total_val;//股票总价格
void set_tot(){total_val = shares * share_val; }
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
(1)访问控制
- private:私有部分,数据隐藏,默认为private
- public:通过公有接口调用私有数据
访问控制 | 可访问范围 |
---|---|
private | 该类函数、友元函数访问,该类对象不能访问 |
protected | 该类函数、子类函数、友元函数访问,该类对象不能访问 |
public | 该类函数、子类函数、友元函数、该类对象访问 |
(2)实现类的成员函数
定义成员函数时,使用::来指出函数所属的类
定义位于类声明中的函数会自动成为内联函数
void Stock::buy(long num, double price)
{
//可以访问类的私有成员
}
(3)使用类
#include<iostream>
#include"stock00.h"
#include "stock00.cpp"
int main()
{
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();
return 0;
}
三、类的构造函数和析构函数
1.构造函数:
用于构造新对象,将值赋给他们的数据成员,名称与类名相同,没有返回值,但是也没有被声明类型,构造函数中的参数名不能与数据成员名相同可以给数据成员前加前缀m_
Stock(const string & co, long n = 0, double pr = 0.0);
Stock food = Stock("World Cabbage", 250, 1.25);//显式调用
Stock garment("Furry Mason", 50, 2.5);//隐式调用
Stock *pstock = new Stock("abc", 18, 19.0);//使用指针调用
构造函数无法被对象调用,如果没有提供构造函数,C++将自动提供默认构造函数。在构建类时,为他提供默认构造函数和非默认构造函数
//默认构造函数
Stock::Stock(){
company = "no name";
shares = 0;
share_val = 0.0;
total_val = 0.0;
}
2.析构函数
程序会提供默认的析构函数
~Stock();//该析构函数什么也不做
void Stock::show() const//该函数不会修改调用对象
四、C++中的this指针
当类成员函数涉及到两个对象时,这种情况需要C++的this指针,两个对象分别显式和隐式引用,const代表不改变它们,this指针为调用它的对象的地址。this是指针,因此返回的是*this。
const Stock & Stock::topval(const Stock & s) const
{
if(s.total_val > total_val)
return s;
else
return *this;
}
五、对象数组
const int STKS = 4;
Stock stocks[STKS] = {
Stock("NanoSmart",12.5,20),
Stock()
};
六、类作用域
要调用公有成员函数,必须通过对象。定义成员函数时,必须使用作用域解析运算符。
七、运算符重载(多态的一种)
operator op(argument list)
Time sum(const Time & t) const;
Time operator+ (const Time & t);
- 重载的运算符至少有一个操作数是用户自定义的类型
- 不能违反运算符原来的句法规则,不能修改优先级
- 不能创造新运算符
八、友元
通过让函数称为类的友元,可以赋予该函数与类的成员函数相同的访问权限。如果使用成员函数,则该对象必须作为第一个操作数。
在重载二元运算符,并且其操作数不是调用对象(例如乘以一个实数)时,就需要使用友元。
//在类声明中写,但是它是非成员函数
friend Time operator*(ouble m, const Time & t);
//定义时不需要Time::
friend Time operator*(ouble m, const Time & t)
{
return t * m;//翻转顺序即可,不一定要使用友元
}
使用由原来重载cout
ostream& operator<<(ostream & os, const Time & t)
{
os << ...;
return os;
}
//传递的是cout本身,
//返回ostream& 对象是因为要实现cout << x << y的形式
九、 注意事项
- 不要返回局部变量或临时对象的引用。函数执行完毕后,局部变量和临时对象会消失,引用将指向不存在的数据。
十、参考教材
C++ PrimerPlus 第六版