《C++ primerplus》第13章练习题
1.对CD类的派生练习。基类CD类存储作者和作品号等信息,派生类Classic额外增加一格“主要作品”的信息。主函数使用拷贝构造函数、按引用传递参数的函数和指针来测试基类和派生类的功能。
注意继承类和基类的权限关系、初始化成员列表的使用。
class.h
#ifndef _CLASS_H_
#define _CLASS_H_ #include <iostream>
using std::cin;
using std::cout; class CD
{
private:
char performers[20] = {}; //初始化为空,不然输出一堆烫
char label[20] = {};
int selections;
double playtime; public:
CD(const char *s1, const char*s2, int n, double x); //自定义构造函数
CD(const CD & d); //拷贝构造函数
CD(); //默认构造函数
virtual ~CD();
virtual void Report()const;
virtual CD & operator = (const CD & d); }; class Classic :public CD
{
private:
char collection[50] = {}; public:
Classic(const char *c, const char *s1, const char*s2, int n, double x);
Classic();
~Classic();
void Report()const;
Classic & operator = (const Classic & d);
}; #endif
DefineClass.cpp
#include "class.h" CD::CD(const char *s1, const char*s2, int n, double x)
{
for (int i = 0; s1[i] != '\0'; i++)
{
performers[i] = s1[i];
}
for (int i = 0; s2[i] != '\0'; i++)
{
label[i] = s2[i];
}
selections = n;
playtime = x;
} CD::CD(const CD & d)
{
for (int i = 0; d.performers[i] != '\0'; i++)
{
performers[i] = d.performers[i];
}
for (int i = 0; d.label[i] != '\0'; i++)
{
label[i] = d.label[i];
}
selections = d.selections;
playtime = d.playtime;
} CD::CD()
{ } CD::~CD()
{ } void CD::Report()const
{
cout << "Performers: ";
for (int i = 0; performers[i] != '\0'; i++)
{
cout << performers[i];
}
cout << "\n";
cout << "Label: ";
for (int i = 0; label[i] != '\0'; i++)
{
cout << label[i];
}
cout << "\n";
cout << "Selections: " << selections << "\n";
cout << "Playtime: " << playtime << "\n";
} CD & CD::operator=(const CD & d)
{
for (int i = 0; d.performers[i] != '\0'; i++)
{
performers[i] = d.performers[i];
}
for (int i = 0; d.label[i] != '\0'; i++)
{
label[i] = d.label[i];
}
selections = d.selections;
playtime = d.playtime; return *this;
} //derived class Classic::Classic(const char *c, const char *s1, const char*s2, int n, double x):CD(s1,s2,n,x)
{
for (int i = 0; c[i] != '\0'; i++)
{
collection[i] = c[i];
}
} Classic::Classic()
{ } Classic::~Classic()
{ } void Classic::Report()const
{
CD::Report();
cout << "Collection: ";
for (int i = 0; collection[i] != '\0'; i++)
{
cout << collection[i];
}
cout << "\n\n";
} Classic & Classic::operator = (const Classic & d)
{
CD::operator=(d);
for (int i = 0; d.collection[i] != '\0'; i++)
{
collection[i] = d.collection[i];
}
return *this;
}
main.cpp
#include "class.h" void Bravo(const CD & disk); int main()
{
CD c1("Beatles", "Capitol", 14, 35.5);
Classic c2 = Classic("Piano Sonata in B flat, Fantasia in C", "Alfred Brendel", "Philips", 2, 57.17); CD *pcd = &c1; cout << "Using Object directly:\n";
c1.Report();
c2.Report(); cout << "Using type cd * pointer to objects:\n";
pcd->Report();
pcd = &c2;
pcd->Report(); cout << "Calling a function with a cd reference argument:\n";
Bravo(c1);
Bravo(c2); cout << "Testing assignment:\n";
Classic copy;
copy = c2;
copy.Report(); //pause
cin.get();
return 0; } void Bravo(const CD & disk)
{
disk.Report();
}
2.以上题为基础。存储的字符数组用使用动态分配内存。
我初始化对象的时候把两个字符成员都设为了空指针,做题的过程中,了解到了空指针不能被赋值。其它需要注意的地方见注释。
ClassCD.h
#ifndef _CLASSCD_
#define _CLASSCD_ #include <iostream> using std::cout;
using std::cin; //Base Class Declare
class CD
{
private:
char *performers = nullptr;
char *label = nullptr;
int selections;
double playtime; public:
CD(const char *s1, const char*s2, int n, double x); //自定义构造函数
CD(const CD & d); //拷贝构造函数
CD(); //默认构造函数
virtual ~CD();
virtual void Report()const;
virtual CD & operator = (const CD & d);
}; //Base Class Define
CD::CD(const char *s1, const char*s2, int n, double x)
{
//根据s1和s2的长度分配内存
//strlen()计算的长度不包含终止符'\0'
//为了不影响report()的执行,分配的内存长度+1,使其包含'\0'
performers = new char[strlen(s1)+1];
for (int i = 0; i < (strlen(s1)+1); i++)
{
performers[i] = s1[i];
} label = new char[strlen(s2)+1];
for (int i = 0; i < (strlen(s2)+1); i++)
{
label[i] = s2[i];
} selections = n;
playtime = x;
} CD::CD()
{
selections = 0;
playtime = 0;
} CD::CD(const CD & d)
{
int count; //对象分配内存的成员不是空指针才会赋值,防止内存访问混乱
if (d.performers != nullptr)
{
//获取等号右边的类里面分配的长度
for (count = 0; d.performers[count] != '\0'; count++)
{
;
} //根据它的长度来分配自身的长度,加上'\0'一位
performers = new char[count + 1]; //给自身成员变量赋值,取到终止符后停止
for (int i = 0; d.performers[i] != '\0'; i++)
{
performers[i] = d.performers[i];
if (d.performers[i + 1] == '\0')
{
performers[i + 1] = '\0';
break;
}
}
} //以下同理
if (d.label != nullptr)
{
for (count = 0; d.label[count] != '\0'; count++)
{
;
} label = new char[count + 1]; for (int i = 0; d.label[i] != '\0'; i++)
{
label[i] = d.label[i];
if (d.label[i + 1] == '\0')
{
label[i + 1] = '\0';
break;
}
}
} selections = d.selections;
playtime = d.playtime;
} CD::~CD()
{
//是空指针,说明从未分配过内存,不需要释放
//不是空指针,说明分配了内存,需要释放
if (performers != nullptr)
{
delete[] performers;
}
if (label != nullptr)
{
delete[] label;
}
} void CD::Report()const
{
//对象分配内存的成员不是空指针才会打印,防止内存访问混乱
cout << "Performers: ";
if (performers != nullptr)
{
for (int i = 0; performers[i] != '\0'; i++)
{
cout << performers[i];
}
}
cout << "\n"; cout << "Label: ";
if (label != nullptr)
{
for (int i = 0; label[i] != '\0'; i++)
{
cout << label[i];
}
}
cout << "\n"; cout << "Selections: " << selections << "\n";
cout << "Playtime: " << playtime << "\n";
} CD & CD::operator=(const CD & d)
{
int count; //对象分配内存的成员不是空指针才会赋值,防止内存访问混乱
if (d.performers != nullptr)
{
//获取等号右边的类里面分配的长度
for (count = 0; d.performers[count] != '\0'; count++)
{
;
} //根据它的长度来分配自身的长度,加上'\0'一位
performers = new char[count + 1]; //给自身成员变量赋值,取到终止符后停止
for (int i = 0; d.performers[i] != '\0'; i++)
{
performers[i] = d.performers[i];
if (d.performers[i + 1] == '\0')
{
performers[i + 1] = '\0';
break;
}
}
} //以下同理
if (d.label != nullptr)
{
for (count = 0; d.label[count] != '\0'; count++)
{
;
} label = new char[count + 1]; for (int i = 0; d.label[i] != '\0'; i++)
{
label[i] = d.label[i];
if (d.label[i + 1] == '\0')
{
label[i + 1] = '\0';
break;
}
}
} selections = d.selections;
playtime = d.playtime; return *this;
} //Derived Class Declare
class Classic :public CD
{
private:
char *collection = nullptr; public:
Classic(const char *c, const char *s1, const char*s2, int n, double x);
Classic();
~Classic();
void Report()const;
Classic & operator = (const Classic & d);
}; //Derived Class Define
Classic::Classic(const char *c, const char *s1, const char*s2, int n, double x) :CD(s1, s2, n, x)
{
collection = new char[strlen(c) + 1];
for (int i = 0; i < (strlen(c) + 1); i++)
{
collection[i] = c[i];
}
} Classic::Classic()
{ } Classic::~Classic()
{
if (collection != nullptr)
{
delete[] collection;
}
} void Classic::Report()const
{
CD::Report();
cout << "Collection: ";
if (collection != nullptr)
{
for (int i = 0; collection[i] != '\0'; i++)
{
cout << collection[i];
}
}
cout << "\n\n";
} Classic & Classic::operator = (const Classic & d)
{
CD::operator=(d);
int count; if (d.collection != nullptr)
{
for (count = 0; d.collection[count] != '\0'; count++)
{
;
} collection = new char[count + 1]; for (int i = 0; d.collection[i] != '\0'; i++)
{
collection[i] = d.collection[i];
if (d.collection[i + 1] == '\0')
{
collection[i + 1] = '\0';
break;
}
}
} return *this;
} #endif
main.cpp
#include "ClassCD.h" void Bravo(const CD & disk); int main()
{
CD c1("Beatles", "Capitol", 14, 35.5);
Classic c2 = Classic("Piano Sonata in B flat, Fantasia in C", "Alfred Brendel", "Philips", 2, 57.17); CD *pcd = &c1; cout << "Using Object directly:\n";
c1.Report();
c2.Report(); cout << "Using type cd * pointer to objects:\n";
pcd->Report();
pcd = &c2;
pcd->Report(); cout << "Calling a function with a cd reference argument:\n";
Bravo(c1);
Bravo(c2); cout << "Testing assignment:\n";
Classic copy;
copy = c2;
copy.Report(); //pause
cin.get();
return 0; } void Bravo(const CD & disk)
{
disk.Report();
}
3.不想使用原题所以没用,目的是练习抽象基类的继承。
所谓抽象基类,就是把定义的基类之中的虚成员函数声明为纯虚的(virtual修饰的函数后面加个 = 0),那么这个基类就只能用于继承,而不能实例化。一旦在代码里试图去实例化,编译之前就会提示“不允许使用抽象类型XXX的对象”。
抽象基类是抽象出一系列对象的共性的做法,方便派生出许多相似的对象。 需要注意,基类定义的纯虚函数不给出定义,而由所有派生类给出自己的定义。
下面是自己简单的练习。定义一个MovingObject的抽象基类,nowwhere()显示当前目标的位置,set_speed()设定目标的速度。从MovingObject派生出Car和Plane对象,各自的构造函数、析构函数、nowwhere()和set_speed()方法都不同。Car类会在坐标轴上按上下左右四个方向移动,Plane类指定一个目标地点,用动态数组的方式存储和打印该地点。
class.h
#ifndef _CLASS_H_
#define _CLASS_H_ #include <iostream>
#include <string> using std::cout;
using std::cin;
using std::string; /* Abstract Base Class */
class MovingObject
{
protected:
double x;
double y;
double v;
string name; public:
MovingObject();
virtual ~MovingObject();
virtual void nowwhere() = 0; //pure virtual function
virtual void set_speed(unsigned int vv) = 0; //pure virtual function
}; MovingObject::MovingObject()
{
} MovingObject::~MovingObject()
{
} /* Derived Class A */
class Car :public MovingObject
{
public:
enum car_direction
{
UP = 0,
DOWN,
LEFT,
RIGHT,
RESET
}drive_to; private: public:
Car();
Car(const double xx, const double yy);
~Car();
void move(car_direction drive_to,double t);
void nowwhere();
void set_speed(unsigned int vv);
}; Car::Car()
{
name = "car";
x = 0;
y = 0;
v = 30;
cout << "A new car constructed.\n";
} Car::Car(const double xx, const double yy)
{
name = "car";
x = xx;
y = yy;
v = 30;
cout << "A new car constructed.\n";
} Car::~Car()
{
cout << "Car decontructed\n";
} void Car::move(car_direction drive_to = RESET,double t = 0)
{
switch (drive_to)
{
case(UP):
{
cout << "The car's moving up, " << "with " << v << " m/s in " << t << " s.\n";
y = y + v * t;
break;
}
case(DOWN):
{
cout << "The car's moving down, " << "with " << v << " m/s in " << t << " s.\n";
y = y - v * t;
break;
}
case(LEFT):
{
cout << "The car's moving left, " << "with " << v << " m/s in " << t << " s.\n";
x = x - v * t;
break;
}
case(RIGHT):
{
cout << "The car's moving right, " << "with " << v << " m/s in " << t << " s.\n";
x = x + v * t;
break;
}
case(RESET):
{
cout << "The car's at (0,0).\n";
x = 0;
y = 0;
v = 1;
break;
}
default:
{
break;
}
}
} void Car::nowwhere()
{
cout << name << " is at (" << x << "," << y << ").\n";
} void Car::set_speed(unsigned int vv)
{
v = vv;
} /* Derived Class B */
class Plane:public MovingObject
{
private:
char *flywhere; public:
Plane();
~Plane();
void nowwhere();
void set_speed(unsigned int vv); }; Plane::Plane()
{
flywhere = new char[20];
char wishplace[20] = {};
v = 180;
cout << "A plane just arrived.\n";
cout << "Assign one destination you wish: ";
cin >> wishplace;
for (int i = 0; i < (strlen(wishplace)+1); i++)
{
flywhere[i] = wishplace[i];
}
} Plane::~Plane()
{
cout << "Plane deconstructed.\n";
delete[] flywhere;
} void Plane::nowwhere()
{
cout << "The plane's flying at " << v << " m/s.\n";
cout << "Finally it arrived at ";
for (int i = 0; flywhere[i] != '\0'; i++)
{
cout << flywhere[i];
}
cout << ".\n";
} void Plane::set_speed(unsigned int vv)
{
cout << "Changing speed to (150~250): ";
if ((vv >= 150) && (vv <= 250))
{
v = vv;
}
else
{
cout << "Invalid speed! (Current: " << v << " m/s.)";
}
} #endif
main.cpp
#include "Class.h" int main()
{
Car car1;
car1.move(Car::UP,10);
car1.nowwhere(); Plane plane1;
plane1.set_speed(180);
plane1.nowwhere(); //pause
cin.get();
cin.get(); return 0; }
输出结果:
4.派生练习。定义存储酒相关信息的类和派生类。
对原题问题的回答:
(a)见代码。
(b)Port有所有默认参数的构造函数和默认构造函数冲突了。
(c)运算符=重载的函数应用的对象算不同的类型,运算符<<重载的函数是友元函数,友元函数不归属于类,也不能被继承,所以不需要声明为虚。
(d)见代码。
Class.h
#ifndef _CLASS_H_
#define _CLASS_H_ #include <iostream>
using std::ostream;
using std::cout;
using std::cin; //Base Class
class Port
{
private:
char * brand;
char style[20]; //tawny,ruby,vintage...
int bottles; public:
Port(const char *br, const char *st, int b); //重新定义,去掉默认参数,防止与默认构造函数重复
Port(); //创建的默认构造函数
Port(const Port & p);
virtual ~Port() { delete[]brand; }
Port & operator = (const Port & p);
Port & operator += (int b); //add bottles
Port & operator -= (int b);
int BottleCount()const { return bottles; }
virtual void show()const;
friend ostream & operator << (ostream & os, const Port & p);
}; Port::Port(const char *br, const char *st, int b = 0)
{
brand = new char[strlen(br) + 1];
for (int i = 0; i < (strlen(br) + 1); i++)
{
brand[i] = br[i];
}
for (int i = 0; i < (strlen(st) + 1); i++)
{
style[i] = st[i];
}
bottles = b; } Port::Port()
{
brand = new char[20];
brand[0] = '\0';
style[0] = '\0';
bottles = 0; } Port::Port(const Port & p)
{
for (int i = 0; i<strlen(p.brand)+1; i++)
{
brand[i] = p.brand[i];
}
for (int i = 0; p.style[i]!='\0'; i++)
{
style[i] = p.style[i];
}
bottles = p.bottles; } Port & Port::operator = (const Port & p)
{
for (int i = 0; i<strlen(p.brand)+1; i++)
{
brand[i] = p.brand[i];
}
for (int i = 0; i < strlen(p.style) + 1; i++)
{
style[i] = p.style[i];
}
bottles = p.bottles; return *this;
} Port & Port::operator += (int b)
{
bottles += b;
return *this;
} Port & Port::operator -= (int b)
{
bottles -= b;
return *this;
} void Port::show()const
{
cout << "Brand:";
for (int i = 0; brand[i] != '\0'; i++)
{
cout << brand[i];
}
cout << "\n";
cout << "Kind:";
for (int i = 0; style[i] != '\0'; i++)
{
cout << style[i];
}
cout << "\n";
cout << "Bottles:" << bottles << "\n";
} ostream & operator << (ostream & os, const Port & p)
{
os << "Brand:";
for (int i = 0; p.brand[i] != '\0'; i++)
{
cout << p.brand[i];
}
os << "\n";
os << "Kind:";
for (int i = 0; p.style[i] != '\0'; i++)
{
os << p.style[i];
}
os << "\n";
os << "Bottles:" << p.bottles << "\n"; return os; } //Derived Class
class VintagePort :public Port
{
private:
char *nickname;
int year; public:
VintagePort();
VintagePort(const char * br, int b, const char *nn, int y);
VintagePort(VintagePort & vp);
~VintagePort() { delete[]nickname; }
VintagePort & operator = (const VintagePort & vp);
void show() const;
friend ostream & operator << (ostream & os, const VintagePort & vp);
}; VintagePort::VintagePort()
{
nickname = new char[20];
nickname[0] = '\0';
year = 0;
} VintagePort::VintagePort(const char * br, int b, const char *nn, int y):Port(br,"none",b)
{
nickname = new char[strlen(nn) + 1];
for (int i = 0; i < strlen(nn) + 1; i++)
{
nickname[i] = nn[i];
}
year = y;
} VintagePort::VintagePort(VintagePort & vp)
{
for (int i = 0; i < strlen(vp.nickname) + 1; i++)
{
nickname[i] = vp.nickname[i];
}
year = vp.year;
} void VintagePort::show()const
{
Port::show();
cout << "Nickname:";
for (int i = 0; nickname[i] != '\0'; i++)
{
cout << nickname[i];
}
cout << "\n";
cout << "Year:" << year;
cout << "\n";
} VintagePort & VintagePort::operator = (const VintagePort & vp)
{
Port::operator=(vp); for (int i = 0; i < strlen(vp.nickname) + 1; i++)
{
nickname[i] = vp.nickname[i];
}
year = vp.year; return *this;
} ostream & operator << (ostream & os, const VintagePort & vp)
{
cout << "Nickname:";
for (int i = 0; vp.nickname[i] != '\0'; i++)
{
os << vp.nickname[i];
}
os << "\n";
os << "Year:" << vp.year;
os << "\n"; return os; } #endif
main.cpp
#include "Class.h" int main()
{
cout << "-- p1 using default constructor -- \n";
Port p1;
p1.show(); cout << "-- p2 using custom constructor -- \n";
Port p2("Gallo", "vintage", 20);
p2.show(); cout << "-- p2 add 20 bottles -- \n";
p2 += 20;
p2.show(); cout << "-- copy p2 -> p1 -- \n";
p1 = p2;
p1.show(); cout << "-- cout << p1 -- \n";
cout << p1; cout << "-- vp1 using default constructor -- \n";
VintagePort vp1;
vp1.show(); cout << "-- vp2 using custom constructor -- \n";
VintagePort vp2("Ruby", 10, "pussy", 1998);
vp2.show(); cout << "-- copy vp2 -> vp1 -- \n";
p1 = p2;
vp1 = vp2;
vp1.show(); cout << "-- copy p2 -> p1 -- \n";
p1 = p2;
cout << vp2; cout << "-- cout << vp1 -- \n";
cout << vp1; //pause
cin.get(); return 0; }
《C++ primerplus》第13章练习题的更多相关文章
- ASM:《X86汇编语言-从实模式到保护模式》第13章:保护模式下内核的加载,程序的动态加载和执行
★PART1:32位保护模式下内核简易模型 1. 内核的结构,功能和加载 每个内核的主引导程序都会有所不同,因为内核都会有不同的结构.有时候主引导程序的一些段和内核段是可以共用的(事实上加载完内核以后 ...
- Linux就这个范儿 第13章 打通任督二脉
Linux就这个范儿 第13章 打通任督二脉 0111010110……你有没有想过,数据从看得见或看不见的线缆上飞来飞去,是怎么实现的呢?数据传输业务的未来又在哪里?在前面两章中我们学习了Linux网 ...
- 《深入Java虚拟机学习笔记》- 第13章 逻辑运算
<深入Java虚拟机学习笔记>- 第13章 浮点运算
- 《Android开发艺术探索》读书笔记 (13) 第13章 综合技术、第14章 JNI和NDK编程、第15章 Android性能优化
第13章 综合技术 13.1 使用CrashHandler来获取应用的Crash信息 (1)应用发生Crash在所难免,但是如何采集crash信息以供后续开发处理这类问题呢?利用Thread类的set ...
- APUE读书笔记-第13章-守护进程
第13章 守护进程 13.1 引言 *守护进程也称精灵进程(daemon)是生存期较长的一种进程.它们常常在系统自举时启动,仅在系统关闭时才终止.因为它们没有控制终端,所以说它们是在后台运行的.UNI ...
- 第13章 模版方法模式(Template Method)
原文 第13章 模版方法模式(Template Method) 模板模式 模板模式 举例:模拟下数据库的update方法,先删除在插入. 1 2 3 4 5 6 7 8 9 10 11 12 13 ...
- 【机器学习实战】第13章 利用 PCA 来简化数据
第13章 利用 PCA 来简化数据 降维技术 场景 我们正通过电视观看体育比赛,在电视的显示器上有一个球. 显示器大概包含了100万像素点,而球则可能是由较少的像素点组成,例如说一千个像素点. 人们实 ...
- 【STM32H7教程】第13章 STM32H7启动过程详解
完整教程下载地址:http://forum.armfly.com/forum.php?mod=viewthread&tid=86980 第13章 STM32H7启动过程详解 本章教 ...
- 【RL-TCPnet网络教程】第13章 RL-TCPnet之TCP服务器
第13章 RL-TCPnet之TCP服务器 本章节为大家讲解RL-TCPnet的TCP服务器实现,学习本章节前,务必要优先学习第12章TCP传输控制协议基础知识.有了这些基础知识之后,再搞本 ...
随机推荐
- 复杂一点的SQL语句:Oracle DDL和DML
DDL:对表或者表的属性进行了改变 create:创建表创建用户创建视图 创建表 create table student(id int,score int) ; student后面与括号之间可以有空 ...
- AppStore SDK
ios审核被拒4.3 http://www.cocoachina.com/bbs/read.php?tid-1731757.html ios审核4.3被拒? 别担心 这几步让你的 App 顺利过审 h ...
- vue 组件内的守卫
1.beforeRouteEnter () // 进入该组件之前要去进行的逻辑操作, 2.beforeRouteLeave() // 离开该组件之前要去进行的逻辑操作(可清除定时器等耗用内存的变量, ...
- 一文吃透redis持久化,妈妈再也不担心我面试过不了!
持久化介绍 redis 提供了两种方式方式进行数据的持久化(将数据存储到硬盘中):第一种称为快照(snapshotting)RDB,它将某一时刻的所有数据都写入硬盘,所以快照是一次全量备份,并且存储的 ...
- java初探(1)之秒杀的安全
在秒杀的场景中还存在着很多的安全问题 暴露秒杀地址 秒杀请求可以很频繁 接口流量大,恶意刷接口 隐藏秒杀接口 为什么需要隐藏,事实上,页面上的所有东西都能被客户端拿到,包括js代码,因此,分析商品详情 ...
- 浅析LR.Net工作流引擎
在当代信息化软件系统开发中,工作流引擎是其中非常重要的一环.所谓工作流引擎,是指工作流作为软件系统的一部分, 其中包括了流程的节点管理.流向管理.流程样例管理.审核管理等重要功能. 工作流引擎可根据角 ...
- oracle之二控制文件
控制文件 3.1 控制文件的功能和特点: 1)定义数据库当前物理状态,不断在往controlfile写入[SCN等] 2)维护数据的一致性 3)是一个二进制文件 ...
- selenuim中18种定位方式
18种定位方式=8种单数形式+8种复数形式+2种底层方案 单数可以确定唯一,复数无法确定: 单数形式定位,返回的是一个元素,复数形式,返回的是一个列表,返回的是当前页面所有符合要求的元素,没有意义 一 ...
- [算法与数据结构]使用Java泛型实现栈
###题解 1 实现内部类node 2 维护top为头节点的链表 3 操作 操作1:push() 操作2: pop() 操作3: isEmpty() ###代码 package Exam; class ...
- 基于k8s的集群稳定架构
前言 我司的集群时刻处于崩溃的边缘,通过近三个月的掌握,发现我司的集群不稳定的原因有以下几点: 1.发版流程不稳定 2.缺少监控平台[最重要的原因] 3.缺少日志系统 4.极度缺少有关操作文档 5.请 ...