c++笔记(持续更新)

37 篇文章 1 订阅

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、多态

参考博客
多态可以参考自己的案例:
链接
提取码:x4ee

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

inline函数

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 就是
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值