1、不能在类声明中初始化静态成员变量
比如在a.h中 , 类有一个属性
static int num;
在a.h中可以声明,但是不能初始化
在a.cpp中可以赋值 ,比如
int 类名::num=0;
2、new delete
对于 类的构造函数中用到了new 堆区 ,记得要在对应的析构函数中delete掉。
删除类定义的对象,可以删掉对象本身占用的内存,但无法自动释放对象成员的指针指向的内存,因此必须使用析构delete掉。
str=new char[len+1];
delete str[];
3、函数的参数传递还是建议用引用传递
4、复制构造函数
Port(const Port& p);
5、深度复制
StringBad & StringBad::operator=(const StringBad &st)
{
//省略其他语句
return *this;
}
6、静态成员函数
可以直接在类声明中写好定义
比如在 a.h中
static int houmany() { return num;}
也可以在a.h中
static int houmany();
再在a.cpp中
类名::int houmany()
{
return num;
}
7、初始化列表
8、队列模拟
队列是一种抽象的数据类型
以c++ primer plus 第12章课后编程习题最后一题为例
queu.h文件
#pragma once
#ifndef QUEUE_H_
#define QUEUE_H_
#include<iostream>
#include <cstdlib>
using namespace std;
class Customer
{
private:
long arrive;//达到时间
int processtime;//处理时间
public:
Customer()
{
arrive = processtime = 0;
}
void set(long when);
long when() const
{
return arrive;
}
int ptime() const
{
return processtime;
}
};
typedef Customer Item;
class Queue
{
private:
struct Node
{
Item item;
struct Node* next;
};
enum { Q_SIZE = 10 };
Node* front;
Node* rear;
int items;
const int qsize;
Queue(const Queue& q) : qsize(0) { }
Queue& operator=(const Queue& q)
{
return *this;
}
public:
Queue(int qs = Q_SIZE);
~Queue();
bool isempty() const;
bool isfull() const;
int queuecount() const;
bool enqueue(const Item& item);
bool dequeue(Item& item);
};
#endif
queue.cpp
// queue.cpp -- Queue and Customer methods
#include "queue.h"
Queue::Queue(int qs) : qsize(qs)
{
front = rear = NULL;
items = 0;
}
Queue::~Queue()
{
Node* temp;
while (front != NULL)
{
temp = front;
front = front->next;
delete temp;
}
}
bool Queue::isempty() const
{
return items == 0;
}
bool Queue::isfull() const
{
return items == qsize;
}
int Queue::queuecount() const
{
return items;
}
bool Queue::enqueue(const Item& item)
{
if (isfull())
return false;
Node* add = new Node;
add->item = item;
add->next = NULL;
items++;
if (front == NULL)
front = add;
else
rear->next = add;
rear = add;
return true;
}
bool Queue::dequeue(Item& item)
{
if (front == NULL)
return false;
item = front->item;
items--;
Node* temp = front;
front = front->next;
delete temp;
if (items == 0)
rear = NULL;
return true;
}
void Customer::set(long when)
{
processtime = std::rand() % 3 + 1;
arrive = when;
}
main.cpp
// bank.cpp -- using the Queue interface
// compile with queue.cpp
#include <iostream>
#include <cstdlib>
#include <ctime>
#include "queue.h"
const int MIN_PER_HR = 60;
bool newcustomer(double x);
int main()
{
using std::cin;
using std::cout;
using std::endl;
using std::ios_base;
std::srand(std::time(0));
cout << "Case Study: Bank of Heather Automatic Teller\n";
cout << "Enter maximum size of queue: ";
int qs;
cin >> qs;
Queue line1(qs);
Queue line2(qs);
cout << "The simulation hours: 100\n";
int hours = 100;
long cyclelimit = MIN_PER_HR * hours;
double perhour;
double min_per_cust;
perhour = 1;
Item temp;
long turnaways = 0;
long customers = 0;
long served = 0;
long sum_line = 0;
int wait_time1 = 0;
int wait_time2 = 0;
int line1_size = 0;
int line2_size = 0;
long line_wait = 0;
double avetime = 0;
while (perhour++ && avetime <= 1)
{
while (!line1.isempty())
{
line1.dequeue(temp);
}
while (!line2.isempty())
{
line2.dequeue(temp);
}
min_per_cust = MIN_PER_HR / perhour;
for (int cycle = 0; cycle < cyclelimit; cycle++)
{
if (newcustomer(min_per_cust))//这里的判断很重要 等待时间小于1min的才能加进去
{
if (line1.isfull() && line2.isfull())//如果队列1 队列2 都满了
turnaways++;//处理不了的客户++
//判断一下进队列1 还是 队列2
else if (line1_size < line2_size)
{
customers++;
temp.set(cycle);//把此时的cycle设置为客户到达时间
line1.enqueue(temp);
line1_size++;
}
else
{
customers++;
temp.set(cycle);
line2.enqueue(temp);
line2_size++;
}
}
if (wait_time1 <= 0 && !line1.isempty())
{
line1.dequeue(temp);
line1_size--;
wait_time1 = temp.ptime();
line_wait += cycle - temp.when();//累计时间-到达时间=等待时间 下面同理
served++;
}
if (wait_time2 <= 0 && !line2.isempty())
{
line2.dequeue(temp);
line2_size--;
wait_time2 = temp.ptime();
line_wait += cycle - temp.when();
served++;
}
if (wait_time1 > 0)
wait_time1--;
if (wait_time2 > 0)
wait_time2--;
sum_line += line1.queuecount();
sum_line += line2.queuecount();
}
if (customers > 0)
{
cout << "customers accepted: " << customers << endl;//总共的客户
cout << " customers served: " << served << endl;//处理的客户
cout << " turnaways: " << turnaways << endl;//未处理的客户
cout << "average queue size: ";//
cout.precision(2);
cout.setf(ios_base::fixed, ios_base::floatfield);
cout << (double)sum_line / cyclelimit << endl;
cout << " average wait time: " << (double)line_wait / served << " minutes\n";
}
else
cout << "No customers!\n";
avetime = (double)line_wait / served;
}
cout << "When there comes " << perhour << " people per hour, the average wait time will be about 1 minute.\n";
cout << "Done!\n";
system("pause");
return 0;
}
bool newcustomer(double x)//对每个客户随机判断(是否小于1min)
{
return (std::rand() * x / RAND_MAX < 1);
}
9、父类与子类 继承
自行阅读下面的代码即可
main.cpp
#include"port.h"
#include<iostream>
using namespace std;
int main()
{
Port port1("gallo", "tawny", 20);
cout<<port1<<endl;//这就是<<重载的作用
VintagePort vp1("gallo", "vintage", 24, "Old Velvet", 16);
VintagePort vp2(vp1);
cout << vp2 << endl;
VintagePort vp3=vp1;
//vp3 = vp1;先声明 再赋值也可以
cout << vp3 << endl;
Port* p_port;//父类指针
p_port = &port1;
p_port->Show();
cout << endl;
p_port = &vp1;//父类指针指向子类对象
p_port->Show();
cout << endl;
return 0;
}
port.h
#pragma once
#include<iostream>
using namespace std;
//父类
class Port
{
public:
Port(const char * br = "none",const char *st ="none" ,int b=0 );//初始化
Port(const Port &p);//拷贝构造?
virtual ~Port() { delete[]brand; }//析构
Port& operator=(const Port& p);//重载赋值运算符----针对整个对象
Port& operator+=(int b);//针对对象的成员
Port& operator-=(int b);//针对对象的成员
int BottleCount() const { return bottles; }
virtual void Show() const;//重载函数---子类
friend ostream& operator<<(ostream& os, const Port& p);//友元,在类外定义
private:
char* brand;//牌子
char style[20];
int bottles;
};
//子类
class VintagePort :public Port
{
public:
VintagePort() :Port(), nickname(nullptr), year(0) {} //初始化列表
//Port() 就是 Port(const char * br = "none",const char *st ="none" ,int b=0 )
VintagePort(const char* br, const char* st,int b, const char* nn, int y);//有参构造
VintagePort(const VintagePort& vp);
~VintagePort() { delete[]nickname; }
VintagePort& operator=(const VintagePort& vp);
void Show() const;
friend ostream& operator<<(ostream& os, const VintagePort& vp);
private:
char* nickname;//
int year;//年份
};
port.cpp
#include"port.h"
Port::Port(const char* br, const char* st, int b)
{
this->brand = new char[strlen(br) + 1];//加1是为了把空格符加进去
strcpy_s(this->brand, strlen(br) + 1, br);
strcpy_s(this->style, st);
this->style[19] = '\0';
this->bottles = b;
}
Port::Port(const Port& p)
{
this->brand = new char[strlen(p.brand) + 1];
strcpy_s(this->brand, strlen(p.brand) + 1, p.brand);
strcpy_s(this->style, p.style);
this->bottles = p.bottles;
}
//
Port& Port::operator=(const Port& p)
{
char* temp = brand;//让temp指向原brand指向的地方
brand = new char[strlen(p.brand) + 1];//给brand开辟新空间
strcpy_s(brand, strlen(p.brand) + 1, p.brand);
strcpy_s(style, p.style);
bottles = p.bottles;
delete[]temp;//释放原brand内存
return *this;
}
//
Port& Port::operator+=(int b)
{
this->bottles += b;
return *this;
}
Port& Port::operator-=(int b)
{
if (this->bottles >= b)
this->bottles -= b;
else
cout << "error";
return *this;
}
void Port::Show() const
{
cout << "Brand: " << brand << '\n';
cout << "Kind: " << style << '\n';
cout << "Bottles: " << bottles << '\n';
}
//友元 输出
ostream& operator<<(ostream& os, const Port& p)
{
os << p.brand << ", " << p.style << ", " << p.bottles;
return os;
}
VintagePort::VintagePort(const char* br, const char* st,
int b, const char* nn, int y) : Port(br, st, b)
{
this->nickname = new char[strlen(nn) + 1];
strcpy_s(this->nickname, strlen(nn) + 1, nn);
this->year = y;
}
VintagePort::VintagePort(const VintagePort& vp) :Port(vp)//vp是const因此要在函数体外给父类赋值
{
this->nickname = new char[strlen(vp.nickname) + 1];
strcpy_s(this->nickname, strlen(vp.nickname) + 1, vp.nickname);
this->year = vp.year;
}
VintagePort& VintagePort::operator=(const VintagePort& vp)
{
char* temp = this->nickname;
Port::operator=(vp);
this->nickname = new char[strlen(vp.nickname) + 1];
strcpy_s(this->nickname, strlen(vp.nickname) + 1, vp.nickname);
this->year = vp.year;
delete[] temp;
return *this;
}
void VintagePort::Show()const
{
Port::Show();
cout << "Nickename: " << nickname << '\n';
cout << "Year: " << year << '\n';
}
//友元 输出
ostream& operator<<(ostream& os, const VintagePort& vp)
{
os << (const Port&)vp;
os << ", " << vp.nickname << ", " << vp.year;
return os;
}
10、虚函数
虚函数的作用:通过以下两个程序来进行解释!
可以让成员函数操作一般化,用基类的指针指向不同的派生类的对象时,
基类指针调用其虚成员函数,则会调用其真正指向对象的成员函数,
而不是基类中定义的成员函数(只要派生类改写了该成员函数)。
若不是虚函数,则不管基类指针指向的哪个派生类对象,调用时都
会调用基类中定义的那个函数
(1)
#include <iostream>
using namecpace std;
class B0 //基类B0声明
{
public:
void display(){cout<<"B0::display()"<<endl;} //公有成员函数
};
class B1: public B0
{
public:
void display(){cout<<"B1::display()"<<endl;}
};
class D1: public B1
{
public:
void display(){cout<<"D1::display()"<<endl;}
};
void fun(B0 *ptr)
{
ptr->display(); //"对象指针->成员名"
}
void main() //主函数
{
B0 b0; //声明B0类对象
B1 b1; //声明B1类对象
D1 d1; //声明D1类对象
B0 *p; //声明B0类指针
p=&b0; //B0类指针指向B0类对象
fun(p);
p=&b1; //B0类指针指向B1类对象
fun(p);
p=&d1; //B0类指针指向D1类对象
fun(p);
}
运行结果:
B0::display()
B0::display()
B0::display()
(2)
#include <iostream>
using namespace std;
class B0 //基类B0声明
{public: //外部接口
virtual void display() //虚成员函数
{cout<<"B0::display()"<<endl;}
};
class B1: public B0 //公有派生
{ public:
void display() { cout<<"B1::display()"<<endl; }
};
class D1: public B1 //公有派生
{ public:
void display() { cout<<"D1::display()"<<endl; }
};
void fun(B0 *ptr) //普通函数
{ ptr->display(); }
void main() //主函数
{ B0 b0, *p; //声明基类对象和指针
B1 b1; //声明派生类对象
D1 d1; //声明派生类对象
p=&b0;
fun(p); //调用基类B0函数成员
p=&b1;
fun(p); //调用派生类B1函数成员
p=&d1;
fun(p); //调用派生类D1函数成员
}
运行结果:
B0::display()
B1::display()
D1::display()
11、访问控制:protected
private 和 protected的区别只有在基类派生类的类中才会表现出来
派生类的成员可以直接访问基类的保护成员,但不能直接访问基类的私有成员。
总结:
对于外部世界来说,保护成员的行为和私有成员相似。
对于派生类来说,保护成员的行为与公有成员相似。
12、构造函数 析构函数、赋值运算符不能继承
如果编译器发现一个程序将一个对象
对象属于派生类,编译器将使用基类的赋值运算符处理派生类对象中基类部分的赋值。
如果显式地为基类提供了赋值运算符,将使用该运算符。与此类似,如果成员是另一个类的对象,则对于该成员,将使用其所属类的赋值运算符。
如果派生类使用了new,则必须提供显式赋值运算符。
父类的赋值运算符
Port& Port::operator=(const Port& p)
{
char* temp = brand;//让temp指向原brand指向的地方
brand = new char[strlen(p.brand) + 1];//给brand开辟新空间
strcpy_s(brand, strlen(p.brand) + 1, p.brand);
strcpy_s(style, p.style);
bottles = p.bottles;
delete[]temp;//释放原brand内存
return *this;
}
子类的赋值运算符
VintagePort& VintagePort::operator=(const VintagePort& vp)
{
char* temp = this->nickname;
Port::operator=(vp);//这里调用基类的赋值运算
this->nickname = new char[strlen(vp.nickname) + 1];
strcpy_s(this->nickname, strlen(vp.nickname) + 1, vp.nickname);
this->year = vp.year;
delete[] temp;
return *this;
}
13、私有继承
这意味着基类方法将不会成为派生类对象的公有接口,但可以在派生类的成员函数中使用它们。
在不进行显式类型转换的情况下,不能将指向派生类的引用或指针赋给基类引用或指针。
class 类名 :private 基类
{
}
14、多重继承—MI
class 类名 :private 基类1, private 基类2,....
{
}
(1)没有用到虚基类的多重继承
(2)用到虚基类的多重继承
15、is-a(is-a-kind-of)关系
公有继承创建了is-a关系
16、保护继承
class 类名 :protected 基类
{
}
17、各种继承
18、虚基类
有一个类A,A中有个成员 i
B和C都继承了A
D又同时继承了B和C
那么D中的i是来自于B还是来自于C呢?
这时候就要用到虚基类(虚继承)
此时B和C继承的是同一个对象A,而不是2个A
这样i都是来自于一个对象
#include<iostream>
using namespace std;
class A
{
public:
int i;
void showa(){cout<<"i="<<i<<endl;}
};
class B:virtual public A //此处采用虚继承
{
public:
int j;
};
class C:virtual public A //此处采用虚继承
{
public:
int k;
};
class D:public B,public C
{
public:
int m;
};
int main()
{
D d;
d.i=4; //这个A中的i,是从B那边继承而来的,还是从C那边继承而来的呢?
//所以B和C必须进行虚继承,A是B和C的虚基类
//若将虚继承去掉,则编译错误
d.showa();
return 0;
}
19、多态
20、ch14 课后题
3、
template.h
#pragma once
//另外一个头文件,包含了类的声明和实现
#ifndef QUEUETP_H_
#define QUEUETP_H_
//模板类
template <class T>
class QueueTp
{
private:
enum {Q_SIZE= 10 };
struct Node { T item; Node* next; };
int items;
const int qsize;
QueueTp(const QueueTp & q):qsize(0) {}
QueueTp& operator=(const QueueTp& q) { return *this; };
public:
Node* front;
Node* rear;
QueueTp(int qs=Q_SIZE):qsize(qs)
{
front = rear = nullptr;
items = 0;
}//设置空间大小
~QueueTp()
{
Node* temp;
while (front != nullptr)
{
temp = front;
front = front->next;
delete temp;
}
}
bool isempty() const;//
bool isfull();//
int queuecount() const;
bool Push(const T &item);//从头部添加
bool Pop(T &item);//删除尾部数据,其实根本不是删除尾部数据,只是让人访问不到最后一个数据
};
template <class T>
bool QueueTp<T>::isempty() const
{
return items == 0;
}
template <class T>
bool QueueTp<T>::isfull()
{
return items == qsize;
}//
template <class T>
int QueueTp<T>::queuecount() const
{
return items;
}
template <class T>
bool QueueTp<T>::Push(const T &item)
{
if (isfull())
return false;
Node* temp = new Node;
temp->item = item;
temp->next = nullptr;
if (front == nullptr)
front = temp;
else
rear->next = temp;
rear = temp;
return true;
}
template <class T>
bool QueueTp<T>::Pop(T &item)//
{
if (isempty())
return false;
item = front->item;
items--;
Node* temp = front;
front = front->next;
delete temp;
if (items == 0)
{
rear = nullptr;
}
return true;
}
#endif
worker.h
#pragma once
//头文件,类的声明
#ifndef WORKERMI_H_
#define WORKERMI_H_
#include <iostream>
#include <string>
using namespace std;
class Worker//基类
{
private:
std::string fullname;
long id;
protected:
//
void Data() const;//
void Get();//
public:
Worker() : fullname("no one"), id(0L) {}//无参构造
Worker(const std::string& s, long n)//有参构造
: fullname(s), id(n) {}
~Worker() {};//析构
void Set() ;
void Show() const ;//
};
//class Waiter : virtual public Worker //虚继承
//{
//private:
// //自己的属性
// int panache;//
//protected:
// void Data() const;//重载的
// void Get();//重载的
//public:
// Waiter() : Worker(), panache(0) {}
// Waiter(const std::string& s, long n, int p = 0)//这是初始化panche
// : Worker(s, n), panache(p) {}
// Waiter(const Worker& wk, int p = 0)
// : Worker(wk), panache(p) {}
// void Set();
// void Show() const;
//};
//
//class Singer : virtual public Worker//虚继承
//{
//protected:
// enum {//枚举 0-6
// other, alto, contralto, soprano,
// bass, baritone, tenor
// };
// enum { Vtypes = 7 };
// //重载
// void Data() const;//
// void Get();//
//private:
// //自己的属性
// static char* pv[Vtypes];
// int voice;
//public:
// Singer() : Worker(), voice(other) {}
// Singer(const std::string& s, long n, int v = other)
// : Worker(s, n), voice(v) {}
// Singer(const Worker& wk, int v = other)
// : Worker(wk), voice(v) {}
// void Set();
// void Show() const;
//};
//
//class SingingWaiter : public Singer, public Waiter//同时继承上面两个类,所以上面两个用续继承
//{
//protected:
// void Data() const;
// void Get();
//public:
// SingingWaiter() {}
// SingingWaiter(const std::string& s, long n, int p = 0, int v = other)
// : Worker(s, n), Waiter(s, n, p), Singer(s, n, v) {}//有参构造---初始化列表
// SingingWaiter(const Worker& wk, int p = 0, int v = other)//把 子类自己的属性初始化
// : Worker(wk), Waiter(wk, p), Singer(wk, v) {}
// SingingWaiter(const Worker& wt, int v = other)
// : Worker(wt), Waiter(wt), Singer(wt, v) {}
// SingingWaiter(const Singer& wt, int p = 0)
// : Worker(wt), Waiter(wt, p), Singer(wt) {}
// void Set();
// void Show() const;
//};
#endif
worker.cpp
#include"worker.h"
//worker类方法实现
//必须实现虚析构函数,即使是纯虚函数
void Worker::Show() const
{
cout << "Name: " << fullname << endl;
cout << "Employee ID: " << id << endl;
}
void Worker::Set()
{
cout << "Enter worker's Name: ";
getline(cin, fullname);
cout << "Enter worker's ID: ";
cin >> id;
while (cin.get() != '\n')
continue;
}
waiter类方法实现
//void Waiter::Set()
//{
// cout << "Enter waiter's name: ";
// Worker::Get();
// Get();
//}
//
//void Waiter::Show() const
//{
// cout << "Category: waiter\n";
// Worker::Data();
// Data();
//}
//
//void Waiter::Get()
//{
// cout << "Enter worker's panche rating: ";
// cin >> panache;
// while (cin.get() != '\n')
// continue;
//}
//
//void Waiter::Data() const
//{
// cout << "Panache rating: " << panache << endl;
//}
//
singer类方法实现
//char* Singer::pv[Singer::Vtypes] = { "other", "alto", "contralto",
// "soprano", "bass", "baritone", "tensor" };
//
//void Singer::Set()
//{
// cout << "Enter singer's name: ";
// Worker::Get();
// Get();
//}
//
//void Singer::Show() const
//{
// cout << "Category: singer\n";
// Worker::Data();
// Data();
//}
//
//void Singer::Data() const
//{
// cout << "Vocal range: " << pv[voice] << endl;
//}
//
//void Singer::Get()
//{
// cout << "Enter number for singer's vocal range:\n";
// int i;
// for (i = 0; i < Vtypes; i++)
// {
// cout << i << ": " << pv[i] << " ";
// if (i % 4 == 3)
// cout << endl;
// }
// if (i % 4 != 0)
// cout << endl;
// cin >> voice;
// while (cin.get() != '\n')
// continue;
//}
//
singingwaiter类方法实现
//void SingingWaiter::Data() const
//{
// Singer::Data();
// Waiter::Data();
//}
//
//void SingingWaiter::Get()
//{
// Waiter::Get();
// Singer::Get();
//}
//
//void SingingWaiter::Set()
//{
// cout << "Enter singing waiter's name: ";
// Worker::Get();
// Get();
//}
//
//
//void SingingWaiter::Show() const
//{
// cout << "Categroy: singing waiter\n";
// Worker::Data();
// Data();
//}
5、
emp.h
//书中的头文件程序
#include <iostream>
#include <string>
using std::string;
class abstr_emp
{
private:
string fname;
string lname;
string job;
public:
abstr_emp();
abstr_emp(const string& fn, const string& ln,
const string& j);
virtual void ShowAll() const;
virtual void SetAll();
friend std::ostream& operator<<(
std::ostream& os, const abstr_emp& e);
virtual ~abstr_emp() = 0;
};
class employee : public abstr_emp
{
public:
employee(const string& fn, const string& ln,
const string& j);
virtual void ShowAll() const;
virtual void SetAll();
};
class manager : virtual public abstr_emp
{
private:
int inchargeof;
protected:
int InChargeOf() const { return inchargeof; }
int& InChargeOf() { return inchargeof; }
public:
manager();
manager(const string& fn, const string& ln,
const string& j, int ico = 0);
manager(const abstr_emp& e, int ico);
manager(const manager& m);
virtual void ShowAll() const;
virtual void SetAll();
};
class fink : virtual public abstr_emp
{
private:
string reportsto;
protected:
const string ReportsTo() const { return reportsto; }
string& ReportsTo() { return reportsto; }
public:
fink();
fink(const string& fn, const string& ln,
const string& j, const string& rpo);
fink(const abstr_emp& e, const string& rpo);
fink(const fink& f);
virtual void ShowAll() const;
virtual void SetAll();
};
class highfink : public manager, public fink
{
public:
highfink();
highfink(const string& fn, const string& ln,
const string& j, const string& rpo, int ico);
highfink(const abstr_emp& e, const string& rpo, int ico);
highfink(const fink& f, int ico);
highfink(const manager& m, const string& rpo);
highfink(const highfink& h);
virtual void ShowAll() const;
virtual void SetAll();
};
emp.cpp
//类的实现
#include <iostream>
#include <string>
#include "emp.h"
using namespace std;
abstr_emp::abstr_emp()
{
fname = "no name";
lname = "no name";
job = "no job";
}
abstr_emp::abstr_emp(const string& fn,
const string& ln, const string& j)
{
fname = fn;
lname = ln;
job = j;
}
abstr_emp::~abstr_emp() {}
void abstr_emp::ShowAll() const
{
cout << "First name: " << fname << endl;
cout << "Last name: " << lname << endl;
cout << "Job:" << job << endl;
}
void abstr_emp::SetAll()
{
cout << "Enter the first name: " << endl;
getline(cin, fname);
cout << "Enter the last name: " << endl;
getline(cin, lname);
cout << "Enter the job: " << endl;
getline(cin, job);
}
std::ostream& operator<<(ostream& os, const abstr_emp& e)
{
os << e.fname << " " << e.lname;
return os;
}
employee::employee(const string& fn, const string& ln,
const string& j) : abstr_emp(fn, ln, j)
{
}
void employee::ShowAll() const
{
abstr_emp::ShowAll();
cout << endl;
}
void employee::SetAll()
{
abstr_emp::SetAll();
}
manager::manager()
{
inchargeof = 0;
}
manager::manager(const string& fn, const string& ln, const string& j,
int ico) : abstr_emp(fn, ln, j), inchargeof(ico)
{
}
manager::manager(const abstr_emp& e, int ico)
: abstr_emp(e), inchargeof(ico)
{
}
manager::manager(const manager& m) : abstr_emp(m)
{
inchargeof = m.inchargeof;
}
void manager::ShowAll() const
{
abstr_emp::ShowAll();
cout << "Inchargeof: " << inchargeof << endl;
cout << endl;
}
void manager::SetAll()
{
abstr_emp::SetAll();
cout << "Enter the inchargeof: " << endl;
cin >> inchargeof;
while (cin.get() != '\n')
continue;//数字和字符混合输入时注意
}
fink::fink()
{
reportsto = "no name";
}
fink::fink(const string& fn, const string& ln, const string& j,
const string& rpo) : abstr_emp(fn, ln, j), reportsto(rpo)
{
}
fink::fink(const abstr_emp& e, const string& rpo)
: abstr_emp(e), reportsto(rpo)
{
}
fink::fink(const fink& f) : abstr_emp(f)
{
reportsto = f.reportsto;
}
void fink::ShowAll() const
{
abstr_emp::ShowAll();
cout << "Reportsto: " << reportsto << endl;
cout << endl;
}
void fink::SetAll()
{
abstr_emp::SetAll();
cout << "Enter the reportsto: " << endl;
getline(cin, reportsto);
}
highfink::highfink()
{
}
highfink::highfink(const string& fn, const string& ln, const string& j,
const string& rpo, int ico) : abstr_emp(fn, ln, j), fink(fn, ln, j, rpo), manager(fn, ln, j, ico)
{
}
highfink::highfink(const abstr_emp& e, const string& rpo, int ico)
: abstr_emp(e), fink(e, rpo), manager(e, ico)
{
}
highfink::highfink(const fink& f, int ico)
: abstr_emp(f), fink(f), manager(f, ico)
{
}
highfink::highfink(const manager& m, const string& rpo)
: abstr_emp(m), fink(m, rpo), manager(m)
{
}
highfink::highfink(const highfink& h) : abstr_emp(h), fink(h), manager(h)
{
}
void highfink::ShowAll() const
{
manager::ShowAll();
cout << "Reportsto: " << ReportsTo() << endl;
cout << endl;
}
void highfink::SetAll()
{
manager::SetAll();
cout << "Enter the reportsto: " << endl;
getline(cin, fink::ReportsTo());//将cin 接收的输入赋给reportsto ReportsTo()返回的就是reportsto
}
main.cpp
#include<iostream>
#include"emp.h"
using namespace std;
int main()
{
employee em("Trip", "Harris", "Thumper");
cout << em << endl;
em.ShowAll();
manager ma("Amorphia", "Spindragon", "Nuancer", 5);
cout << ma << endl;
ma.ShowAll();
fink fi("Matt", "Oggs", "Oiler", "Juno Barr");
cout << fi << endl;
fi.ShowAll();
highfink hf(ma, "Curly Kew");
hf.ShowAll();
cout << "Press a key for next phase:\n";
cin.get();
highfink hf2;
hf2.SetAll();
cout << "Using an abstr_emp * pointer:\n";
abstr_emp* tri[4] = { &em, &fi, &hf, &hf2 };
for (int i = 0; i < 4; i++)
tri[i]->ShowAll();
return 0;
}
Effective c++
让自己习惯c++
21、最好以const对象或enum替换#define
22、对于形似函数的宏,最好改用inline函数替换#define
23、尽可能使用const
const_cast<char &>(
static_cast<const TextBlock&>(*this)//将*this从其原始类型TextBlock转为const----因为operator[]返回的是const ,也就是 (*this)[position]
[position]
);//外面的强制转换就是把const移除 因为
24、确定对象被使用前已先被初始化
不同源文件中的对象初始化先后的问题:
用static解决
调用tfs().numDisks();
构造/析构/赋值运算
25、了解c++默默编写并调用哪些函数
26、若不想使用编译器自动生成的函数,就该明确拒绝
27、 为多态基类声明virtual析构函数
28、别让异常逃离析构函数
29、绝不在构造和析构过程中调用virtual函数
30、令operator= 返回一个reference to *this
31、在operator= 中处理“自我赋值”
32、复制对象时忘记其每一个分支
资源管理
33、以对象管理资源
34、在资源管理类中小心copying行为
35、在资源管理类中提供对原始资源的访问
36、成对使用new 和 delete时要采取相同形式
37、以独立语句将newed对象置入智能指针
设计与声明
38、让接口容易被正确使用,不易被误用
39、设计class犹如设计type
40、宁以pass-by-reference-to-const替换pass-by-value
41、必须返回对象时,别妄想返回其reference
注:对于heap-allocated有一个问题:该谁对着被你new出来的对象实施delete。
42、将成员变量声明为private
43、宁以non-member、non-friend替换mumber函数
44、若所有参数姐皆需类型转换,请为此采用non-member函数
45、考虑写出一个不抛出异常的swap函数
不是太懂这个!!!
1 和2 就是