编程语言
首页 > 编程语言> > Coursera课程笔记----C++程序设计----Week3

Coursera课程笔记----C++程序设计----Week3

作者:互联网

类和对象(Week 3)

内联成员函数和重载成员函数

内联成员函数

class B{
  inline void func1(); //方式1
  void func2() //方式2
  {
    
  };
};

void B::func1(){}

成员函数的重载及参数缺省

#include<iostream>
using namespace std;
class Location{
  private:
  	intx,y;
  public:
  	void init(int x=0,int y=0); //存在2个缺省参数
  	void valueX(int val) {x = val;}//1
  	int valueX(){return x;}//2
  //1和2是重载函数
}

构造函数

基本概念

class Complex{
  private:
  	double real,imgae;
  public:
  	void Set(double r, double i);
};//编译器自动生成默认的构造函数

Complex c1;//默认的构造函数被调用
Complex* pc = new Complex;//默认的构造函数被调用

class Complex{
  private:
  	double real,imgae;
  public:
  	Complex(double r, double i = 0);
};
Complex::Complex(double r, double i){
  real = r;
  imag = i;
}

Complex c1; //error,缺少构造函数的参数
Complex *pc = new Complex;//error,没有参数
Complex c1(2); //OK
Complex c1(2,4),c2(3,5);
Complex *pc = new Complex(3,4);
class Complex{
  private:
  	double real,imgae;
  public:
  	void Set(double r, double i);
  	Complex(double r,double i);
  	Complex(double r);
  	Complex(Complex c1,Complexc2);
};

Complex::Complex(double r, double i)
{
  real = r;imag = i;
}

Complex::Complex(double r)
{
  real = r; imag = 0;
}
Complex::Complex(Complex c1, Complex c2)
{
  real = c1.real+c2.real;
  imag = c1.imag+c2.imag;
}
Complex c1(3),c2(1,0),c3(c1,c2);
//c1={3,0} c2={1,0} c3={4,0};

构造函数在数组中的使用

class CSample{
  	int x;
  public:
  	CSample(){
      cout<<"Constructor 1 Called"<<endl;
    }
  	CSample(int n){
      x = n;
      cout<<"Constructor 2 Called"<<endl;
    }
};

int main()
{
  CSample array1[2]; // 1 1
  cout<<"step1"<<endl;
  CSample array2[2] = {4,5};//2 2
  cout<<"step2"<<endl;
  CSample array3[2] = {3};//2 1
  cout<<"step3"<<endl;
  CSample *array4 = new CSample[2];//1 1
  delete []array4; // 收回空间
  return 0;
}
class Test{
  public:
  	Test(int n){ }//(1)
  	Test(int n, int m){ }//(2)
  	Test(){ }//(3)
};
Test array1[3] = {1,Test(1,2)} //三个元素分别用(1),(2),(3)进行初始化
Test array2[3] = {Test(2,3),Test(1,2),1};//2 2 1
Test * pArray[3] = {new Test(4), new Test(1,2)};//1 2 ❌

复制构造函数(copy constructor)

class Complex{
  private:
  	double real,imag;
};
Complex c1;//调用缺省无参构造函数
Complex c2(c1);//调用缺省的复制构造函数,将c2初始化成和c1一样
class Complex{
  public:
  	double real,imag;
  Complex(){ }
  Complex(const Complex & c){
    real = c.real;
    imag = c.imag;
    cout<<"Copy Constructor called";
  }
};
Complex c1;
Complex c2(c1);
class CSample{
  CSample(CSample c){
    //error,不允许这样的构造函数
  }
}

类型转换构造函数

class Complex{
  public:
  	double real,imag;
  	Complex(int i){//类型转换构造函数
      cout<<"IntConstructor called"<<endl;
      real = i;
      imag = 0;
    }
  	Complex(double r, double i) //传统构造函数
    {
      real = r;
      imag = i;
    }
};

iint main()
{
  Complex c1(7,8);//对c1进行初始化,调用传统构造函数
  Complex c2 = 12; //对c2进行初始化,调用类型转换构造函数,不会生成一个临时对象
  c1 = 9; // 赋值语句,虽然赋值号两边类型不同,但是编译器没有报错。
  //编译器以9作为实参,调用类型转换构造函数,9被自动转换成一个临时Complex对象,赋值给c1
}

析构函数(Destructor)

class String{
  private:
  	char *p;
  public:
  String(){
    p = new char[10];
  }
  ~String();
};

String::~String(){
  delete [] p;
}

静态成员变量和静态成员函数

基本概念

如何访问静态成员

  1. 类名::成员名
  2. 对象名.成员名
  3. 指针->成员名
  4. 引用.成员名

静态成员示例

注意事项

成员对象和封闭类

成员对象

class CTyre{ //轮胎类
  private:
  	int radius;
  	int width;
  public:
  	CTyre(int r,int w):radius(r),width(w){ } //这种风格看起来更好一些
};
class CEngine{ //引擎类
}

class CCar{ //汽车类➡️“封闭类”
  private:
  	int price;//价格
  	CTyre tyre;
  	CEngine engine;
  public:
  	CCar{int p, int tr, int tw};
};
CCar::CCar(int p, int tr,int w):price(p),tyre(tr,w){ };

int main()
{
  CCar car(20000,17,225);
  return 0;
}

封闭类构造函数的初始化列表

调用顺序

友元

友元函数

class CCar; // 提前声明CCar类,以便后面CDriver类使用
class CDriver{
  public:
  void ModifyCar(CCar* pCar); //改装汽车
};
class CCar{
  private:
  	int price;
  friend int MostExpensiveCar(CCar cars[],int total); //声明友元
  friend void CDriver::ModifyCar(CCar *pCar);
}

void CDriver::ModifyCar(CCar *pCar)
{
  pCar->price +=1000; //汽车改装后价值增加
}
int MostExpensiveCar(CCar cars[],int total)//求最贵的汽车的价格
{
  int tmpMax = -1;
  for(int i = 0; i < total;++i)
    if(cars[i].price > tmpMax)
      tmpMax = cars[i].price;
  return tmpMax;
}
int main()
{
  return 0;
}
class B{
  public:
  	void function();
};

class A{
  friend void B::function();
};

友元类

class CCar{
  private:
  	int price;
  friend class CDriver; //声明CDriver为友元类
};
class CDriver{
  public:
  	CCar myCar;
  void ModifyCar(){
    myCar.price += 1000; //CDriver是CCar的友元类➡️可以访问其私有成员
  }
};
int main(){return 0;}

this指针

this指针作用

class Complex{
  public:
  	double real,imag;
  	void Print(){
      cout<<real<<","<<imag;
    }
  Complex(double r, double i):real(r),imag(i){ }
  Complex AddOne(){
    this->real++; //=real++
    this->Print();//=Print()
    return *this;
  }
};

int main()
{
  Complex c1(1,1),c2(0,0);
  c2 = c1.AddOne();
  return 0;
}
class A{
  int i;
  public:
  	void Hello(){cout<<"hello"<<endl;}
};//编译器把该成员函数编译成机器指令后,会变成
//void Hello(A *this){cout<<"hello"<<endl;}
//如果Hello函数变成 void Hello(){cout<<i<<"hello"<<endl;}
//就会出错

int main()
{
  A *p = NULL;
  p->Hello(); //结果会怎样?
}//输出:hello
//编译器把该成员函数编译成机器指令后,会变成
//hello(p)

注意事项

常量对象、常量成员函数和常引用

常量对象

常量成员函数

class Sample
{
  public:
  	int value;
  	void GetValue() const;
  	void func(){};
  	Sample(){}
};
void Sample::GetValue() const
{
  value = 0;//wrong
  func();//wrong
}

int main(){
  const Sample o;
  o.value = 100; //err,常量对象不可以被修改
  o.func();//err常量对象上面不能执行非常量成员函数
  o.GetValue();//ok
  return 0;
}

常量成员函数的重载

常引用

const int & r = n;
r = 5;//error
n = 4;//ok

练习题

注:填空题在Coursera提交时,文件中只需出现填进去的内容即可

Quiz 1

#include<iostream>
#include<stdio.h>
#include<cstring>
#include<string>
#include<string.h>
using namespace std;
class A {
public:
    int val;
    A (int n = 0){val = n;}
    A & GetObj(){
        return *this;
    }
};
int main() {
    A a;
    cout << a.val << endl;
    a.GetObj() = 5;
    cout << a.val << endl;
}

Quiz 2

#include<iostream>
#include<stdio.h>
#include<cstring>
#include<string>
#include<string.h>
using namespace std;
class Sample{
public:
    int v;
    Sample(int n):v(n) { }
    Sample(const Sample &a)
    {
        v = a.v*2;
    }
};
int main() {
    Sample a(5);
    Sample b = a;
    cout << b.v;
    return 0;
}

Quiz 3

#include<iostream>
#include<stdio.h>
#include<cstring>
#include<string>
#include<string.h>
using namespace std;
class Base {
public:
    int k;
    Base(int n):k(n) { }
};
class Big {
public:
    int v;
    Base b;
    Big(int n = 5):v(n),b(n){ };
};
int main() {
    Big a1(5); Big a2 = a1;
    cout << a1.v << "," << a1.b.k << endl;
    cout << a2.v << "," << a2.b.k << endl;
    return 0;
}

Quiz 4 魔兽世界之一:备战

#include <iostream>
#include <cstdio>
#include <string>
using namespace std;
const int WARRIOR_NUM = 5;
/*
string Warrior::names[WARRIOR_NUM] = { "dragon","ninja","iceman","lion","wolf" };
红方司令部按照 iceman、lion、wolf、ninja、dragon 的顺序制造武士。
蓝方司令部按照 lion、dragon、ninja、iceman、wolf 的顺序制造武士。
*/

class Headquarter;
class Warrior
{
private:
    Headquarter * pHeadquarter; //指向英雄所属阵营的指针
    int kindNo;//武士的种类编号 0 dragon 1 ninja 2 iceman 3 lion 4 wolf
    int no;//英雄编号
public:
    static string names[WARRIOR_NUM]; //存放5种职业名字的数组
    static int initialLifeValue [WARRIOR_NUM]; //存放不同英雄的起始生命值(从输入中采集)
    Warrior( Headquarter *p,int no_,int kindNo_);//构造函数
    void PrintResult(int nTime); //执行打印数据的工作,若无法继续创建则输出结束并停止
};

class Headquarter
{
private:
    int totalLifeValue;
    bool stopped;
    int totalWarriorNum;
    int color;
    int curMakingSeqIdx; //当前要制造的武士是制造序列中的第几个
    int warriorNum[WARRIOR_NUM]; //存放每种武士的数量
    Warrior * pWarriors[1000];//和每个创建的英雄建立链接
public:
    friend class Warrior;
    static int makingSeq[2][WARRIOR_NUM];//武士的制作序列,按阵营的不同分成两个
    void Init(int color_, int lv); //初始化阵营需要颜色和总血量
    ~Headquarter();
    int Produce(int nTime); //创建英雄,输入时间
    string GetColor();
};

Warrior::Warrior(Headquarter *p, int no_, int kindNo_) {
    no = no_;
    kindNo = kindNo_;
    pHeadquarter = p;
}

void Warrior::PrintResult(int nTime) {
    string color = pHeadquarter->GetColor();
    printf("%03d %s %s %d born with strength %d,%d %s in %s headquarter\n",
            nTime, color.c_str(), names[kindNo].c_str(),no,initialLifeValue[kindNo],
            pHeadquarter->warriorNum[kindNo],names[kindNo].c_str(),color.c_str()); // string 在printf中输出的函数调用c_str()
}

void Headquarter::Init(int color_, int lv) {
    color = color_;
    totalLifeValue = lv;
    totalWarriorNum = 0;
    stopped = false;
    curMakingSeqIdx = 0;
    for (int i = 0; i < WARRIOR_NUM; i++) {
        warriorNum[i] = 0;
    }
}

Headquarter::~Headquarter() {
    for (int i = 0; i < totalWarriorNum; i++) {
        delete pWarriors[i];
    }
}

int Headquarter::Produce(int nTime) {
    if(stopped)
        return 0;
    int searchingTimes = 0;
    while(Warrior::initialLifeValue[makingSeq[color][curMakingSeqIdx]] > totalLifeValue &&
            searchingTimes < WARRIOR_NUM)
    {
        curMakingSeqIdx = (curMakingSeqIdx + 1) % WARRIOR_NUM;
        searchingTimes++;
    }
    int kindNo = makingSeq[color][curMakingSeqIdx];
    if(Warrior::initialLifeValue[kindNo] > totalLifeValue)
    {
        stopped = true;
        if(color == 0)
            printf("%03d red headquarter stops making warriors\n",nTime);
        else
            printf("%03d blue headquarter stops making warriors\n",nTime);
        return 0;
    }
    //排除所有其他条件后,开始制作士兵
    totalLifeValue -= Warrior::initialLifeValue[kindNo];
    curMakingSeqIdx =( curMakingSeqIdx + 1) % WARRIOR_NUM;
    pWarriors[totalWarriorNum] = new Warrior(this,totalWarriorNum+1,kindNo);
    warriorNum[kindNo]++;
    pWarriors[totalWarriorNum]->PrintResult(nTime);
    totalWarriorNum++;
    return 1;
}

string Headquarter::GetColor() {
    if(color == 0)
        return "red";
    else
        return "blue";
}

string Warrior::names[WARRIOR_NUM] = {"dragon","ninja","iceman","lion","wolf"};
int Warrior::initialLifeValue[WARRIOR_NUM];
int Headquarter::makingSeq[2][WARRIOR_NUM]={{2,3,4,1,0},{3,0,1,2,4}};//两个司令部武士的制作顺序序列

int main()
{
    int t;
    int m;
    Headquarter RedHead,BlueHead;
    scanf("%d", &t); //读取case数
    int nCaseNo = 1;
    while(t--){
        printf("Case:%d\n",nCaseNo++);
        scanf("%d",&m);//读取基地总血量
        for (int i = 0; i < WARRIOR_NUM; i++) {
            scanf("%d",&Warrior::initialLifeValue[i]);
        }
        RedHead.Init(0,m);
        BlueHead.Init(1,m);
        int nTime = 0;
        while (true){
            int tmp1 = RedHead.Produce(nTime);
            int tmp2 = BlueHead.Produce(nTime);
            if( tmp1 == 0 && tmp2 == 0)
                break;
            nTime++;
        }
    }
    return 0;
}
//老师给的答案读了好几遍,大概捋顺了……
//现阶段自己根本写不出来这种程序,在第一步抽象出两个类这块就感觉很困难
//慢慢加油吧……

标签:函数,int,成员,Coursera,C++,Complex,Week3,class,构造函数
来源: https://www.cnblogs.com/maimai-d/p/12894078.html