第十章——类和对象
- 学习c++也有一段时间了,一直在工程应用上,也就是能用就行,没有系统地去学习,根据口碑是c++ primer更好,但是手头只有这本,记录一下学习中的收获。
1.面向对象编程
- 面向过程的方法,首先考虑要遵循的步骤,然后考虑如何表示这些数据。
- 面向对象的方法,从用户角度考虑,描述对象所需的数据以及描述用户和数据交互所需的操作。
2.抽象与类
- 类的设计尽量将公有接口和实现细节分开。和数据隐藏等一样,是一种封装。
- 内联函数:如果一个函数是内联的,那么在编译的时候,编译器会把该函数的代码副本放置在每个调用该函数的地方。
要求在每个使用内联函数的文件中定义,所以应将内联定义在类的头文件中。(这点有疑问,可能使用的vs2017有只能链接程序,所以实验不出来)- 优点: 当函数体比较小的时候, 内联该函数可以令目标代码更加高效。
- 缺点: 内联非常短小的存取函数通常会减少代码大小, 但内联一个相当大的函数将戏剧性的增加代码大小.
- 结论: 不要内联超过 10 行的函数. 谨慎对待析构函数, 析构函数往往比其表面看起来要更长, 因为有隐含的成员和基类析构函数被调用,不要内联那些包含循环或 switch 语句的函数。
3.构造函数与析构函数
int year = 2001;
struct thing;
{
char * pn;
int m;
};
thing amabob = {"wodget", -23 };
Stock hot = {"nameOfCompany", 200, 2.2}//Stock 是之前定义的类,这个操作编译错误。
不能像初始化结构体那样初始化类的对象,因为数据部分的访问是私有的(如果设置为公有,就违背了OOP的思想)结构体和类区别之一吧。
- 如果对象是const类型的话(const Stock tencent),调用的成员函数也必须是const类型的。
//这是函数声明
void show() const;
//这是函数定义
void show() const
{
std::cout<<"lalala";
}
/*
否则将出现一下两条错误:
1. E1086 对象含有与成员 函数 "Stock::show" 不兼容的类型限定符 对象类型是: const Stock
2. C2662 “void Stock::show(void)”: 不能将“this”指针从“const Stock”转换为“Stock &”
*/
- C++11还可以将初始化列表的方法用于类
//三个参数意义分别为公司名称,购入股票数,股票的价格
Stock hot_tip = {"tencent", 100, 4.5}
Stock hot_tip {"tencent", 100, 4.5}
- 杂记:c++函数的缺省值是在定义的时候还是在声明的时候定义呢?
声明是用户可以看到的地方,用户相信这个特性。如果在定义的时候与声明不同的话就有问题,所以编译器禁止声明和定义的时候同时定义缺省值。
报错:重定义默认参数 - 默认实参需要在形参列表的结尾,否则会报错。
5.对象数组
//可以这样初始化
const int STKS = 4;
Stock stocks[STKS] =
{
Stock("a", 1.1, 2);
Stock("b", 1.2,3);
Stock("c", 1.3,4);
Stock("d", 1.4,5);
}
6.类作用域
需要创建一个由所有对象共享的常量时,仅仅声明为const int 等类型是不行的。因为声明类只是描述了对象的形式,并没有创建对象。没有用于存储值的空间。具体方法有二
- 方法一:在类中声明一个枚举。
class A
{
private:
enum {Months = 12};
...
- 方法二:声明为静态变量例如 static const int
7.作用域内枚举
8.抽象数据类型 以栈为例。
作业:
注意的细节:
- 1.一个类的名称一般都是首字母大写。
复习题5
/*
* 定义一个类来表示银行账户。数据成员包括储户姓名、账号(使用字符串)和存款。成员函数执行如下操作。
* 创建一个对象并将其初始化;
* 显示储户姓名、账号和存款;
* 存入参数指定的存款
* 取出参数指定的存款
*/
class BankCount
{
private:
string name;
long number;
long deposit;
public:
BankCount();//default constructor
BankCount(std::string name,std::string number,long deposit);//constructor
void show() const;
bool save(int);
bool withdraw(int);
};
编程练习 2
#include <iostream>
#include <string>
using namespace std;
class Person {
private:
static const int LIMIT = 25;
string lname; //person's last name
char fname[LIMIT]; //person's first name
public:
Person(); //{ lname = "", fname[0] = '\0'; }//#1
Person(const string&, const char*fn = "Hey,You.");//#2
void show()const; //first-last
void FormalShow() const;//last-first
};
/*
Person::Person()
{ lname = "", fname[0] = '\0'; }//#*/
Person::Person()
{
lname = "notDefined";
strcpy_s(fname,"NULL");//字符串数组没有在声明的时候初始化的话,只能这么拷贝了。
cout << "default constructor called.\n";
}
Person::Person(const string & lname_, const char* fname_)
{
lname = lname_;
strcpy_s(fname, fname_);
cout << "constructor called.\n";
}
void Person::show() const
{
cout << "name: " << fname << " " << lname << endl;//需要有string头文件才能直接cout
}
void Person::FormalShow() const
{
cout << "name: " << lname << " " << fname << endl;//需要有string头文件才能直接cout
}
int main()
{
Person noOne;
Person me{ "neo","lin" };
noOne.show();
me.show();
system("pause");
}
编程练习5
//stack.h
#pragma once
#ifndef STACK_H_
#define STACK_H_
struct Customer {
char fullname[35];
double payment;
};
typedef Customer Item;
class Stack
{
private:
enum{max=10};
Item items[max];
int top;
double sum = 0;
public:
Stack();//构造函数
bool isEmpty() const;
bool isFull() const;
bool push(const Item & item);
bool pop(Item & item);
void show() const;
};
#endif
//stack.cpp
#include "stack.h"
#include <iostream>
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];
sum += item.payment;
}
else
return false;
}
void Stack::show() const
{
for (int i = 0; i < top; ++i)
{
std::cout << "full name: "<< items[i].fullname << "\t" << "payment: "
<< items[i].payment << std::endl;
}
std::cout << "sum:" << sum << std::endl << std::endl;
}
//main.cpp
#include "stack.h"
#include <iostream>
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];
sum += item.payment;
}
else
return false;
}
void Stack::show() const
{
for (int i = 0; i < top; ++i)
{
std::cout << "full name: "<< items[i].fullname << "\t" << "payment: "
<< items[i].payment << std::endl;
}
std::cout << "sum:" << sum << std::endl << std::endl;
}
第六题
#include <iostream>
#include <string>
#include "stack.h"
using namespace std;
class Move
{
private:
double x;
double y;
public:
Move(double a = 0, double b = 0);
void showmove() const;
Move add(const Move & m) const;
void reset(double a = 0, double b = 0);
};
Move::Move(double a, double b)
{
x = a;
y = b;
}
Move Move::add(const Move & m) const
{
Move temp{ this->x + m.x, this->y + m.y };
return temp;
}
void Move::showmove() const
{
cout << "x:" << x << "\ty:" << y << endl;
}
void Move::reset(double a, double b)
{
x = a;
y = b;
}
int main()
{
Move m1{ 2.2,3.3 }, m2{ 4.4,5.5 };
Move m3 = m1.add(m2);
m3.showmove();
system("pause");
}
第七题
/*
"aaa"的类型是const char *
获取其长度的方法是使用strlen函数
*/
#include <iostream>
#include <string>
#include "stack.h"
using namespace std;
class Plorg
{
private:
char m_name[20];
int m_CI;
public:
Plorg();
Plorg(const char *,int);//因为传入的为const类型的字符串数组,所以这里需要声明为const,不然不能匹配。
void changeCI(int);
void show() const;
};
Plorg::Plorg()
{
strcpy_s(m_name, "Plorga");
m_CI = 50;
}
Plorg::Plorg(const char* name, int CI)
{
if (strlen(name) > 20)
{
cout << "name is too long, name set to default name\n";
strcpy_s(m_name, "Plorga");
m_CI = CI;
}
else
{
strcpy_s(m_name, name);
m_CI = CI;
}
}
void Plorg::changeCI(int CI)
{
m_CI = CI;
}
void Plorg::show() const
{
cout << "CI:" << m_CI << "\tname:" << m_name << endl;
}
int main()
{
Plorg p1, p2 {"mfdsfasfdasdfasdfasdfasdfasdfasdfase",100 };
p1.show();
p1.changeCI(32);
system("pause");
/*
const char* a = "fsdfsadfas";
cout << strlen (a) << endl;
cout << strlen("asfdfasdfasdf") << endl;
system("pause");*/
}
- 杂记:在类的函数范围内,如果传入同类的其他对象,那么私有的成员变量和函数也是可以访问的,如果传入其他类的对象,只能访问公有的数据和函数。